Check equaling enum without parameter - haxe

I use enums but can't find good way to check eqauling.
enum Turn {
A(value:Int);
B(value:Int);
}
class Test {
static function main() {
var turn = Turn.A(100);
//I want to Check turn is Turn.A(any value) without using 'switch'.
if (turn == Turn.A) ...
}
}
Is there any good and simple way to checking?

You can use the .match() function:
if (turn.match(Turn.A(_)))

I haven't tested this, but it might be faster using Type class:
if (Type.enumConstructor(turn) == "A") ...
Because it is unsafe ("A" could be a typo), I suggest to use ExprTools:
import haxe.macro.ExprTools.*;
if (Type.enumConstructor(turn) == toString(macro A)) ...
There is another way, but I don't think it is faster :
if (Type.enumIndex(turn) == Type.enumIndex(A(0))) ...
And you might get condition evaluated to true for different enums:
enum Color { Red; }
if (Type.enumIndex(turn) == Type.enumIndex(Red)) ... // true

Related

What is the idiomatic way to do something when an Option is either None, or the inner value meets some condition?

Is there a more idiomatic way to express something like the following?
fn main() {
let mut foo: Option<u8> = None;
match foo {
Some(foo_val) if ! (foo_val < 5) /* i.e. the negation of my acceptance condition */ => {}
_ => { foo.replace(5); }
}
}
It seems like most of the time there's an alternative to having an arm that doesn't do anything, but I've been unable to find one for this particular case.
What I'd like to say is the more direct if foo.is_none() || /* some way to extract and test the inner value */ { ... }, or perhaps some chaining trick that's eluding me.
// in None case
// │ in Some(_) case
// ┌┴─┐ ┌───────────────────┐
if foo.map_or(true, |foo_val| foo_val < 5) {
// ...
}
For more information see Option::map_or.
There are many ways to do it. One of the simplest (and arguably most readable) is something like this:
if foo.unwrap_or(0) < 5 {
...
}
The above will be true in both cases:
when foo is Some with a value smaller than 5;
when foo is None.
In some more complex scenarios, where the "default" value needs to be calculated and performance is critical, you might want to consider unwrap_or_else.
As Lukas suggested, the map_or method can also be used. Note that arguments passed to map_or are eagerly evaluated, so if performance is critical, you might want to consider map_or_else as an alternative.
You can do it with filter (using the negation of your condition) and is_none:
if foo.filter(|&x| !(x < 5)).is_none() {
// Here either foo was None or it contained a value less than 5
}
I'm not sure I completely understand your question but you can try something like that:
fn main() {
let foo: Option<u8> = None;
let result = foo.filter(|foo_val| !(*foo_val < 5) ).unwrap_or(5);
println!("Result: {result}");
}
More example on Playground
The matches! macro seems like a good fit:
if !matches!(foo, Some(a) if a>=5) { foo.replace(5) }
Rust Playground
I'll throw in another solution just for fun....
foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| if x<5 { 5 } else { x });
or (for this specific example)
foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| u8::max(x, 5));
With filter and or,
foo = foo.filter(|a| *a >= 5)
.or(Some(5));
There is the unstable method Option::is_some_and that has been built for exactly this purpose:
if foo.is_some_and(|foo_val| foo_val < 5) {
// ...
}
As it's unstable, it's currently only usable on nightly. See the tracking issue for up to date information.

Elegant way to check if multiple strings are empty

How can I check if multiple strings are empty in an elegant way? This is how I currently do it:
//if one required field is empty, close the connection
if (registerRequest.Email == "") ||
(registerRequest.PhoneNumber == "")||
(registerRequest.NachName =="") ||
(registerRequest.VorName =="") ||
(registerRequest.Password =="") ||
(registerRequest.VerificationId ==""){
//Could not proceed
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}
Note: You may use the solution below if you keep the "is-valid" condition in your handler, and also if you separate your condition into another function or method.
You can create a simple helper function, which has a variadic parameter, and you can call it with any number of string values:
func containsEmpty(ss ...string) bool {
for _, s := range ss {
if s == "" {
return true
}
}
return false
}
Example using it:
if containsEmpty("one", "two", "") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
if containsEmpty("one", "two", "three") {
fmt.Println("One is empty!")
} else {
fmt.Println("All is non-empty.")
}
Output of the above (try it on the Go Playground):
One is empty!
All is non-empty.
Your example would look like this:
if containsEmpty(registerRequest.Email,
registerRequest.PhoneNumber,
registerRequest.NachName,
registerRequest.VorName,
registerRequest.Password,
registerRequest.VerificationId) {
// One of the listed strings is empty
}
Also registerRequest is a kinda long name, it could be shortened to like r. If you can't or don't want to rename it in the surrounding code and if you want to shorten the condition, you could also do something like this:
If registerRequest is a pointer (or interface), you could also write:
if r := registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}
Actually you can do this even if registerRequest is not a pointer, but then the struct will be copied. If registerRequest is a struct, then you can take its address to avoid having to copy it like this:
if r := &registerRequest; containsEmpty(r.Email,
r.PhoneNumber,
r.NachName,
r.VorName,
r.Password,
r.VerificationId) {
// One of the listed strings is empty
}
As Mario Santini mentioned in comment, a way to increase testability, encapsulate this logic, and decouple it from your handler method (which judging by the number of fields looks like it is at risk of changing at a different rate than your handler) could be to put this logic in a function:
func validRequest(registerRequest ?) bool {
return registerRequest.Email == "" ||
registerRequest.PhoneNumber == "" ||
registerRequest.NachName == "" ||
registerRequest.VorName == "" ||
registerRequest.Password == "" ||
registerRequest.VerificationId == ""
}
This now supports very focused, table driven tests, that can exercise what it means to be a valid request independent of any method involving writing headers.
It allows you to verify the valid/invalid path of your enclosing function, but to have very focused tests here. It also allows you to change what it means to be a valid request and verify it independent of your enclosing function.
You can use a switch:
switch "" {
case registerRequest.Email,
registerRequest.NachName,
registerRequest.Password,
registerRequest.PhoneNumber,
registerRequest.VerificationId,
registerRequest.VorName:
w.WriteHeader(UNABLE_TO_PROCEED)
w.Write([]byte("Unable to register account."))
return
}
https://golang.org/ref/spec#Switch_statements

How to use if let with another statement in swift?

If want to both assign a string and check that its not empty in Swift.
if let alternative3Text = attributes.stringForKey("choiceThree") && alternative3Text != "" {
// do stuff with alternative3Text
}
Is this possible in Swift, or do i have to do a nested if-statement?
Update: As of Swift 3 (Xcode 8), additional clauses are
separated by a comma, not by where:
if let alternative3Text = attributes.string(forKey: "choiceThree"),
alternative3Text != "" {
// do stuff with alternative3Text
}
Update: As of Swift 1.2 (Xcode 6.3 beta), you can combine
optional binding with additional conditions:
if let alternative3Text = attributes.stringForKey("choiceThree") where alternative3Text != "" {
// do stuff with alternative3Text
}
Using switch-case still works but is not necessary anymore for this purpose.
Old answer:
It is not possible with an if statement, but with switch.
A switch case can use a where clause to check for additional conditions
(documentation).
Assuming (from your question) that attributes.stringForKey("choiceThree") returns
String?, the following would work:
switch (attributes.stringForKey("choiceThree")) {
case .Some(let alternative3Text) where alternative3Text != "":
// alternative3Text is the unwrapped String here
default:
break
}
No, you can't require additional expressions to be true in an if let statement. You will need to add additional code to do this in either the form of a nested if statement as you've already mentioned, or in some other way. If your only requirement is to keep this statement looking clean and wouldn't mind moving some of the logic elsewhere, you could always make an extension to what ever type your attributes variable is to add this functionality.
Here's an example if attributes was an instance of NSUserDefaults. (just because it already contains a stringForKey() instance method.)
extension NSUserDefaults {
func nonEmptyStringForKey(key: String) -> String? {
let full = self.stringForKey(key)
return full != "" ? full : nil
}
}
And then use it like this
if let alternative3Text = attributes.nonEmptyStringForKey("choiceThree") {
// stuff
}

Compare enum without considering its arguments

Let me make this clear, I have this enum:
enum Token {
Number(v:Float);
Identifier(v:String);
TString(v:String);
Var;
Assign;
Division;
// and so on
}
I want to check if the value of a variable is an Identifier, but this doesn't work:
if(tk == Token.Identifier) {
It only allows me to compare the values if I pass arguments:
if(tk == Token.Identifier('test')) {
But this will only match if the identifier is 'test', but I want to match any identifier.
Type.enumConstructor(tk) == "Identifier"
Read the Type doc for more methods on enum.
Update (2019-02-04):
At the time of writing this answer it was still Haxe 2.06. Much have changed since then.
At this moment, for Haxe 3 (or 4), I would recommend pattern matching, specifically using single pattern check instead:
if (tk.match(Identifier(_)) ...
which is a short hand for
if (switch tk { case Identifier(_): true; case _: false; }) ...
_ is the wildcard that matches anything.
alternatively:
static function isIdentifier(token : Token) return switch(token) { case Token.Identifier(_): true; default: false; }
Using "using" you should also be able to do:
if(tk.isIdentifier()) {
Or even:
tk.match(Token.Identifier(_));

How does one return from a groovy closure and stop its execution?

I would like to return from a closure, like one would if using a break statement in a loop.
For example:
largeListOfElements.each{ element->
if(element == specificElement){
// do some work
return // but this will only leave this iteration and start the next
}
}
In the above if statement I would like to stop iterating through the list and leave the closure to avoid unnecessary iterations.
I've seen a solution where an exception is thrown within the closure and caught outside, but I'm not too fond of that solution.
Are there any solutions to this, other than changing the code to avoid this kind of algorithm?
I think you want to use find instead of each (at least for the specified example). Closures don't directly support break.
Under the covers, groovy doesn't actually use a closure either for find, it uses a for loop.
Alternatively, you could write your own enhanced version of find/each iterator that takes a conditional test closure, and another closure to call if a match is found, having it break if a match is met.
Here's an example:
Object.metaClass.eachBreak = { ifClosure, workClosure ->
for (Iterator iter = delegate.iterator(); iter.hasNext();) {
def value = iter.next()
if (ifClosure.call(value)) {
workClosure.call(value)
break
}
}
}
def a = ["foo", "bar", "baz", "qux"]
a.eachBreak( { it.startsWith("b") } ) {
println "working on $it"
}
// prints "working on bar"
I think you're working on the wrong level of abstraction. The .each block does exactly what it says: it executes the closure once for each element. What you probably want instead is to use List.indexOf to find the right specificElement, and then do the work you need to do on it.
If you want to process all elements until a specific one was found you could also do something like this:
largeListOfElements.find { element ->
// do some work
element == specificElement
}
Although you can use this with any kind of "break condition".
I just used this to process the first n elements of a collection by returning
counter++ >= n
at the end of the closure.
As I understand groovy, the way to shortcut these kinds of loops would be to throw a user-defined exception. I don't know what the syntax would be (not a grrovy programmer), but groovy runs on the JVM so it would be something something like:
class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}}
try { x.each{ if(it.isOk()) throw new ThisOne(it); false} }
catch(ThisOne x) { print x.foo + " is ok"; }
After paulmurray's answer I wasn't sure myself what would happen with an Exception thrown from within a closure, so I whipped up a JUnit Test Case that is easy to think about:
class TestCaseForThrowingExceptionFromInsideClosure {
#Test
void testEearlyReturnViaException() {
try {
[ 'a', 'b', 'c', 'd' ].each {
System.out.println(it)
if (it == 'c') {
throw new Exception("Found c")
}
}
}
catch (Exception exe) {
System.out.println(exe.message)
}
}
}
The output of the above is:
a
b
c
Found c
But remember that "one should NOT use Exceptions for flow control", see in particular this Stack Overflow question: Why not use exceptions as regular flow of control?
So the above solution is less than ideal in any case. Just use:
class TestCaseForThrowingExceptionFromInsideClosure {
#Test
void testEarlyReturnViaFind() {
def curSolution
[ 'a', 'b', 'c', 'd' ].find {
System.out.println(it)
curSolution = it
return (it == 'c') // if true is returned, find() stops
}
System.out.println("Found ${curSolution}")
}
}
The output of the above is also:
a
b
c
Found c
Today I faced a similar problem while working with each closure. I wanted to break the flow of execution based on my condition but couldn't do it.
The easiest way to do in groovy is to use any() on a list instead of each if you wish to return a boolean based on some condition.
Good ole for loop still works in Groovy for your use case
for (element in largeListOfElements) {
if(element == specificElement){
// do some work
return
}
}

Resources