I know how to check a string is in another string
like this code.
when (myString) {
in "FirstString" -> {
// some stuff
}
in "SecondString" -> {
// some stuff
}
else -> {
// some stuff
}
}
in keyword under the hood calls this method CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false)
the question is this :
is there any way that in this case i can set ignoreCase = true ?
You can declare an ad-hoc local operator function contains for strings before when:
fun main() {
operator fun String.contains(other: String): Boolean = this.contains(other, ignoreCase = true)
when(myString) {
in "firstString" -> ...
}
}
This way that function will be invoked for in operator instead of the one declared in the standard library because it's located in the closer scope.
Note, however, that this trick works only if the original contains function is an extension. If it's a member function, it cannot be overridden with an extension.
You can use toLowerCase() function here :
when (myString.toLowerCase()) {
in "firststring" -> {
// some stuff
}
in "secondstring" -> {
// some stuff
}
else -> {
// some stuff
}
}
For the cases of when, if they're variables toLowerCase() needs to be called on each of them. But, if they're constants, simple using lower case strings will work - "firststring", "secondstring"
Related
I'm using C# 7.0 is type pattern. I'm trying to check if an object is not bool or the bool value equals false. However, the pattern I'm currently using with a bool type is:
if (obj is bool boolean && boolean)
{
/* I'm not doing anything here */
}
else
{
DoSomething();
}
Is there a way to invert this if expression using the same type pattern?
You can also use a constant pattern:
if (!(obj is true))
{
DoSomething();
}
What I want to do is:
1. Parse model from url parameter in endpoint.(ex: media, account)
mysite.com/v1/rest/:model <- :model can be whether 'media', 'account'.
So it will look like:
mysite.com/v1/rest/media
mysite.com/v1/rest/account
2. Use 1, retrieve string and use it for getting corresponding struct.
3. Put it to the method which takes interface{}
My code looks like:
type Media struct {
Caption string
}
type Account struct {
Bio string
}
type AdminController struct {
TableName string
ID int64
}
func (c *AdminController) Get(n *core.Network) {
// I want to put struct to below GetModels method dynamically.
// Not explicitly like this.
total, data, err := c.GetModels(&Media{}, n)
// I want to do this
total, data, err := c.GetModels(caster("media"), n)
if err != nil {
n.Res.Error(err)
} else {
n.Res.Success(total, data)
}
}
Is it possible to implement method which takes string and return corresponding struct? Like this:
func (c *AdminController) caster(model string) interface{} {
if string == "media" {
return &Media{}
} else if string == "account" {
return &Account{}
}
return nil
}
If it's possible, is this a good way to deal with REST request (generic way) Or should I implement response methods one by one following table by table?
If I have to implement REST(4) * number_of_tables methods, it doesn't seem to be efficient. Any advice on this architectural problem will be appreciated.
Say for example you have something like this, trying to make the example as simple as possible.
type Home struct {
Bedroom string
Bathroom string
}
How do you pass the field name, or can you, to a function?
func (this *Home) AddRoomName(fieldname, value string) {
this.fieldname = value
}
Obviously that does not work... The only way I can see to do this is to use two functions which adds a lot of extra code when the struct gets really big and has a lot of similar code.
func (this *Home) AddBedroomName(value string) {
this.Bedroom = value
}
func (this *Home) AddBathroomName(value string) {
this.Bathroom = value
}
The only way that I am aware of is to use reflection:
func (this *Home) AddRoomName(fieldname, value string) {
h := reflect.ValueOf(this).Elem()
h.FieldByName(fieldname).Set(reflect.ValueOf(value))
return
}
http://play.golang.org/p/ZvtF_05CE_
One more idea that comes to my mind is like this, not sure if it makes sense in your case though:
func Set(field *string, value string) {
*field = value
}
home := &Home{"asd", "zxc"}
fmt.Println(home)
Set(&home.Bedroom, "bedroom")
Set(&home.Bathroom, "bathroom")
fmt.Println(home)
http://play.golang.org/p/VGb69OLX-X
Use type assertions on an interface value:
package main
import "fmt"
type Test struct {
S string
I int
}
func (t *Test) setField(name string, value interface{}) {
switch name {
case "S":
t.S = value.(string)
case "I":
t.I = value.(int)
}
}
func main() {
t := &Test{"Hello", 0}
fmt.Println(t.S, t.I)
t.setField("S", "Goodbye")
t.setField("I", 1)
fmt.Println(t.S, t.I)
}
It's not critical but I was wondering. Somewhere in my program I have a switch statement that gets called multiple times with an incremented value, so that all cases should be executed in order. Something like a custom made simple sequencer.
like this:
private function sequence_Crush(step:Int):Void
{
switch(step) {
case 1: {
action_loadCueFile();
seq.next(); //This calls the same function with an increased step
}
case 2: {
action_saveSettings();
seq.next();
}
/// EDIT: Some steps run ASYNC and an event triggers the next step in the sequence
/// like this:
case 3: {
events.once(ENGINE_EVENTS.cut_all_complete, seq.next);
cutTracks();
}
My Question is, Is there any way to replace the manually written numbers (1,2,3,4) on the cases and use a counter somehow, macros maybe? I have tried putting a dynamic counter, but the Haxe compiler complains.
What I tried:
var st:Int = 1;
switch(step) {
case (st++): { // 1
action_loadCueFile();
seq.next();
}
case (st++): { // 2
action_saveSettings();
seq.next();
}
//... etc
Build halted with errors (haxe.exe)
Case expression must be a constant value or a pattern, not an arbitrary expression
I am targeting JS and using Haxe 3.1.3. I have tried that in actionscript and javascript and it works fine. The reason I want to do that, is that if I want do add or remove a step, I have to re-organize manually every other case number.
p.s. I know there are other ways to sequence actions in order, but I like this one, as I have everything in one function and it's easy to see the order of execution in one glance
Thanks for reading :-)
Jason beat me to it by a few minutes...
Case expressions in Haxe must be either constant values or patterns.
But you can accomplish the desired behaviour in a few ways: (a) custom syntax like $next with macros; (b) macro conversion into if-else blocks (Jason's answer); (c) without macros and (mis)using pattern guards.
Custom syntax
A quick and dirty implementation of it follows; it only supports case $next: and there are no syntax checks.
When a case $next: is found, the macro checks if the previous case pattern was a single constant integer i and, in that case, rewrites the pattern to the value of i + 1.
Macro implementation:
// SequenceSwitch.hx
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;
class SequenceSwitch {
public
macro static function build():Array<Field> {
var fields = Context.getBuildFields();
for (f in fields)
switch (f.kind) {
case FFun(func) if (func.expr != null):
func.expr = ExprTools.map(func.expr, transf);
case _:
}
return fields;
}
static function transf(e:Expr):Expr {
return switch (e.expr) {
case ESwitch(expr, cases, def):
var ncases = [];
var prev:Array<Expr> = null;
for (c in cases) {
var cur = switch (c.values) {
case [{ expr : EConst(CIdent("$next")), pos : pos }] if (prev != null):
switch (prev) {
case [{ expr : EConst(CInt(i)) }]:
var next = { expr : EConst(CInt(Std.string(Std.parseInt(i) + 1))), pos : pos };
{ values : [next], guard : c.guard, expr : c.expr };
case _:
c;
}
case _:
c;
};
ncases.push(cur);
prev = cur.values;
}
{ expr : ESwitch(expr, ncases, def), pos : e.pos };
case _:
e;
}
}
}
Usage example:
// Text.hx
#:build(SequenceSwitch.build())
class Test {
static function main() {
sequenceCrush(1);
}
static function sequenceCrush(step:Int) {
switch (step) {
case 1:
trace("do one");
sequenceCrush(++step);
case $next:
trace("do two");
sequenceCrush(++step);
case $next:
trace("do three");
sequenceCrush(++step);
case _:
trace("terminate");
}
}
}
No macros/with guards
Similar behaviour could be achieved by (mis)using guards:
static function sequenceCrush_guards(step:Int) {
var st = 1;
switch (step) {
case next if (next == st++):
trace("do one");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do two");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do three");
sequenceCrush_guards(++step);
case _:
trace("terminate");
}
}
In Haxe 3 switch changed from the JS/Flash style simple matching, which was really not much more than a chain of if/elseif/else statements, to full on pattern matching, which has many more compile-time features, and one of those limitations is that you can't match against a variable, only against constants.
You could use a chain of if (step==st++) {} elseif (step==st++) {} else {} statements for pretty much the same effect. If you're really really addicted to the switch syntax, you could use a macro to get the "classic" switch behaviour. I happened to write one such macro some time ago, take a look at this GIST:
https://gist.githubusercontent.com/jasononeil/5429516/raw/ad1085082530760aa394765d5cd5ebd61a5dbecb/ClassicSwitch.hx
You could then code like this:
class Action
{
static function main()
{
for (currentStep in 0...5) {
var i = 0;
ClassicSwitch.from(switch (currentStep) {
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
});
}
}
}
Which gives me the output:
Action.hx:14: Do step 1
Action.hx:15: Do step 2
Action.hx:16: Do step 3
Action.hx:17: Do step 4
Action.hx:18: Do step 5
If all (or most) of your actions are simple function calls you can alternatively use an array of functions:
var actions = [sequence_Crush.bind(1), // if you want to avoid action index = step - 1
action_loadCueFile,
action_saveSettings,
...];
private function sequence_Crush(step:Int):Void
{
while (step < actions.length)
{
actions[step++]();
}
}
You could also keep this recursive (actions[step++](); if (step < actions.length) { sequence_Crush(step)).
In Dart, there is a convenience method for converting a String to an int:
int i = int.parse('123');
Is there something similar for converting String to bool?
bool b = bool.parse('true');
Bool has no methods.
var val = 'True';
bool b = val.toLowerCase() == 'true';
should be easy enough.
With recent Dart versions with extension method support the code could be made look more like for int, num, float.
extension BoolParsing on String {
bool parseBool() {
return this.toLowerCase() == 'true';
}
}
void main() {
bool b = 'tRuE'.parseBool();
print('${b.runtimeType} - $b');
}
See also https://dart.dev/guides/language/extension-methods
To the comment from #remonh87
If you want exact 'false' parsing you can use
extension BoolParsing on String {
bool parseBool() {
if (this.toLowerCase() == 'true') {
return true;
} else if (this.toLowerCase() == 'false') {
return false;
}
throw '"$this" can not be parsed to boolean.';
}
}
No. Simply use:
String boolAsString;
bool b = boolAsString == 'true';
You cannot perform this operation as you describe bool.parse('true') because Dart SDK is a lightweight as possible.
Dart SDK is not so unified as, for example, NET Framework where all basic system types has the following unification.
IConvertible.ToBoolean
IConvertible.ToByte
IConvertible.ToChar
IConvertible.ToDateTime
IConvertible.ToDecimal
IConvertible.ToDouble
IConvertible.ToInt16
IConvertible.ToInt32
IConvertible.ToInt64
IConvertible.ToSByte
IConvertible.ToSingle
IConvertible.ToString
IConvertible.ToUInt16
IConvertible.ToUInt32
IConvertible.ToUInt64
Also these types has parse method, including Boolean type.
So you cannot to do this in unified way. Only by yourself.
Actually yes, there is!
It's as simple as
bool.fromEnvironment(strValue, defaultValue: defaultValue);
Keep in mind that you may need to do strValue.toLowerCase()