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(_));
Related
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
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 := ®isterRequest; 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
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
}
This questions follows another question of mine.
I don't exactly get what is wrong with my attempt to convert res to a ListSociete in the following test code :
import (
"errors"
"fmt"
"github.com/jmcvetta/neoism"
)
type Societe struct {
Name string
}
type ListSociete []Societe
func loadListSociete(name string) (ListSociete, error) {
db, err := neoism.Connect("http://localhost:7474/db/data")
if err != nil {
return nil, err
}
res := []struct {
Name string `json:"a.name"`
}{}
cq := neoism.CypherQuery{
Statement: `
MATCH (a:Societe)
WHERE a.name = {name}
RETURN a.name
`,
Parameters: neoism.Props{"name": name},
Result: &res,
}
db.Cypher(&cq)
if len(res) == 0 {
return nil, errors.New("Page duz not exists")
}
r := res[0]
return ListSociete(res), nil
}
Is a []struct{Name string} different from a []struct{Name string json:"a.name" } ?
Or is a ListSociete different from a []struct{Name string} ?
Thanks.
You are currently dealing with two different types:
type Societe struct {
Name string
}
and the anonymous one:
struct {
Name string `json:"a.name"`
}
These two would be identical if it wasn't for the tag. The Go Specifications states (my emphasis):
Two struct types are identical if they have the same sequence of fields, and if
corresponding fields have the same names, and identical types, and identical tags.
Two anonymous fields are considered to have the same name. Lower-case field names
from different packages are always different.
So, you can't do a simple conversion between the two. Also, the fact that you are converting slices of the two types makes the conversion problematic. I can see two options for you:
Copy through iteration:
This is the safe and recommended solution, but it is also more verbose and slow.
ls := make(ListSociete, len(res))
for i := 0; i < len(res); i++ {
ls[i].Name = res[i].Name
}
return ls, nil
Unsafe conversion:
Since both types have the same underlying data structure, it is possible to do an unsafe conversion.
This might however blow up in your face later on. Be warned!
return *(*ListSociete)(unsafe.Pointer(&res)), nil
Playground Example: http://play.golang.org/p/lfk7qBp2Gb
So, after some tests, here's whats i found out :
A ListSociete defined as such...
type Societe struct {
Name string `json:"a.name"`
}
type ListSociete []Societe
is different from this :
type ListSociete []struct {
Name string `json:"a.name"`
}
This second solution works, whereas the first doesn't.
So I assume there really is no way to convert (directly without writing an explicit loop) between types with different tags ?
In that case, i'll definitely go with the loop, as using tags directly in types (cf. second solution above) would make my code unreadable and unreusable, also I really have no clue what I would be messing with using the unsafe conversion method. So thanks for confirming different tags made different types.
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
}
}