the following:
var b = map(r, proc(x: string): string = if x.isNilOrEmpty(): "stuff" else: x)
Error: complex statement requires indentation
therefore listening to the compiler, the next:
var b = map(r, proc(x: string): string =
if x.isNilOrEmpty(): "stuff" else: x)
builds.
that, I refuse it.
try putting the expression into parentheses:
var b = map(r, proc(x: string): string = (if x.isNilOrEmpty(): "stuff" else: x))
you could also do it this way:
var b = r.map do (x: string) -> string:
if x.isNilOrEmpty(): "stuff" else: x
or this way:
import future
var b = r.map((x) => (if x.isNilOrEmpty(): "stuff" else: x))
this is better
import sequtils, strutils
var r = @["1", "2", "3"]
var b = r.mapIt( if it.isNilOrEmpty: "empty" else: it )
echo b
@doofenstein : thanks, the do notation still evades my understanding, I need more time before I get it. The => is great, I used it later, but we should not have to put parentheses. @mashingan : better indeed. even though one can argue this convention over configuration can be itchy. now how about a ?? operator like in C# and the expression will become
var b = r.mapIt( it ?? "empty" )
I did this, is this any good ?
proc `??`*[T](thing: T, alternativeIfNil: T): T =
if thing == nil:
return alternativeIfNil
return thing
proc `??`*(thing: string, alternativeIfNil: string): string =
if thing.isNilOrEmpty:
return alternativeIfNil
return thing
doAssert(("" ?? "truc") == "truc")
doAssert((string(nil) ?? "truc") == "truc")
doAssert(((ref int)(nil) ?? new(type(int)))[] == 0)
?? operator can be defined like this:
import strutils
proc `??`[T](val, alternative: T): T =
when T is string:
if val.isNilOrEmpty: return alternative
else:
if val.isNil: return alternative
val
More universal, works with most types:
proc zeroval[T]: T {.compiletime.} = discard
proc `??`[T](val, alternative: T): T =
const zero = zeroval[T]()
if val==zero: return alternative
when compiles(val.len):
if val.len==0: return alternative
val
Tests:
echo " scalars:"
echo(5??7)
echo(0??7)
echo " strings:"
echo("5"??"7")
echo(""??"7")
var s: string # nil
echo(s??"7")
echo " cstrings:"
var cs1, cs2: cstring
cs1 = "5"
cs2 = "7"
echo(cs1??cs2)
cs1 = ""
echo(cs1??cs2)
cs1 = nil
echo(cs1??cs2)
echo " sequencies:"
var x = @["5"]
echo(x ?? @["7"])
x = @[]
echo(x ?? @["7"])
x = nil
echo(x ?? @["7"])
echo " sets:"
var y = {5}
let z = {7}
echo(y??z)
y.excl 5
echo(y??z)
echo " objects:"
var a = Slice[int](a:5,b:55)
let b = Slice[int](a:7,b:77)
echo(a??b)
reset(a)
echo(a??b)
echo " tuples:"
var c = (5,55)
let d = (7,77)
echo(c??d)
c=(0,0)
echo(c??d)
echo " pointers:"
var v1 = 5
var v2 = 7
var r1 = addr v1
var r2 = addr v2
echo (r1 ?? r2)[]
r1 = nil
echo (r1 ?? r2)[]
echo " chaining:"
let
s1: string = nil
s2 = ""
s3 = "5"
s4 = "7"
echo s1??s2??s3??s4
Didn't think about laziness, indeed, it should. :)
proc zeroval[T]: T {.compiletime.} = discard
template `??`[T](val, alternative: T): T =
const zero = zeroval[T]()
if val==zero:
alternative
else:
when compiles(val.len):
if val.len==0: alternative
else: val
else: val
@LeuGim thank you very much. can you edit your code to add proc zeroval[T]: T {.compiletime.} = discard so that future googlers can copy paste with no struggle ?
Also let's mention some keywords so that PageRank can index efficiently: ?? is the "null coalescing operator" or "nil coalescing operator". And it can be chained. a ?? b ?? c ?? d...
Updated.
Yes, can be chained, updated the examples too.
Also let's mention some keywords
Don't know... "empty coalescing"?.. "double question"? Probably it can be found by just 2 words "coalescing operator" when combined with "Nim".