Interpolate without creating a String context in Raku? - string

If I have a variable my $a = True, then I get this output from the following code:
say «a list of words foo $a bar baz».raku;
# OUTPUT: ("a", "list", "of", "words", "foo", "True", "bar", "baz")
That is, even though the result is a List, the element True is stringified before being included in the list – the list contains "True", not True. Is there any way to avoid that stringification while still using interpolation?
Would there be a way to do so if $a were a class I'd defined (and thus can write the Str method for) rather than a Bool?
(I am aware that I can write the more verbose ("a", "list", "of", "words", "foo", $a, "bar", "baz") or «a list of words foo».Slip, $a, «bar baz».Slip, but I'm asking if there is a way to still use interpolation).

Interpolation is putting a thing into a string.
"a b c $thing d e f"
It does that by first turning the thing itself into a string, and concatenating the rest of the string around it.
Basically the above compiles into this code:
infix:<~>( 「a b c 」, $thing.Str, 「 d e f」 )
« a b c $thing »
Is short for:
Q :double :quotewords « a b c $thing d e f »
That is use the Quoting DSL, turning on :double quote semantics (“”) and turning on :quotewords.
:quotewords is the feature which splits the string into its individual parts.
It happens only after it has been turned into a string.
Imagine that the above compiles into:
Internals::quotewords( infix:<~>( 「 a b c 」, $thing.Str, 「 d e f 」 ) )
There is another way to get what you want, other than using .Slip or prefix |.
flat «a list of words foo», $a, «bar baz»
The whole purpose of the quoting DSL is that it produces a string.
That said :words, :quotewords, and :val all change it so that it returns something other than a single string.
And the idea of them is that they alter the DSL.
So MAYBE you could convince enough people that such a change would be worth it.
Thats a big maybe.
It would potentially break many existing codebases, so you would have an uphill battle to do so.

What happens here has little to do with quoting, and a lot to do with context. As #brad-gilbert has indicated, anything that goes passes through putting ~ in front, which is coercing the variable to a String context.
But that yields an answer to your second question:
Would there be a way to do so if $a were a class I'd defined (and thus can write the Str method for) rather than a Bool?
Theoretically, something like this should work:
class A {
has Bool $.foo;
method Str { $.foo }
};
my $a = A.new( :foo(True) );
say «a b $a».raku
Alas, this returns «No such method 'WORDS_AUTODEREF' for invocant of type 'Bool'␤ so it probably needs a bit of work (or I might have bumped into some bug). So this is, for the time being, and for your precise example, a nanswer. As a matter of fact, only Strs have that method, so I think that for the time being, and unless you bother to create that specialized method for a class, it's difficult to do.

Related

Thinking Functionally. Building a New Array in Haskell / Purescript

I'm new to functional programming, and I've decided to build an app in Purescript. I've hit my first hurdle, and I'm not sure how to think about this conceptually.
I'm not looking for code as much as a way to think functionally about this problem.
I have a list of data. Specifically, something like
[ {a :: String, b :: String, c :: String} ]
I would like to create a list of Html (which is a purescript-halogen type) by using the record provided (with a list of the above types).
So, I would have a function
buildElements :: forall p i. MyRecordObject -> Array (HTML p i)
Now, I think I'm going to need to give this function result type a Monad computational context (purescript Eff is like Haskell IO)
So something like:
buildElements :: forall p i. MyRecordObject -> Eff (Array (HTML p i))
My first idea was vaguely around creating a list with something like
take $ length xs $ repeat ARecordObject
and then map the record over that list, but I wasn't really sure how to translate that into code. It seemed wrong anyway, since my plan involved mutating the state of ARecordObject, which is a no-no.
So then I found this function:
forEach :: forall e a. Array a -> (a -> Eff e Unit) -> Eff Unit
which looks almost perfect! I get an array, I give it a function that somehow assigns the properties in the record to this new array...but no, wait...I'm thinking non-functionally again.
I'm really at a bit of a loss here. Basically, I want to create something like a list of <li></li> elements, where I assign properties to each item.
E.g
I'm provided a record with:
[ { id: "id1", name: "name1", class: "class1", content: "content1" }
, { id: "id2", name: "name2", class: "class2", content: "content2" } ]
And I would like a function foo that returns an array:
[ li [ id_ rec.id, name_ rec.name, class_ rec.class ] [ text rec.content ]
, li [ id_ rec.id, name_ rec.name, class_ rec.lass ] [ text rec.content ] ]
where rec is the name of the recordObject (and obviously the two arrays are not identical, but actually mapped over the initial record).
(the dot syntax is a purescript record syntax notation similar to standard getter/setter notation)
My first idea was vaguely around creating a list with something like
take $ length xs $ repeat ARecordObject
and then map the record over that list, but I wasn't really sure how
to translate that into code. It seemed wrong anyway, since my plan
involved mutating the state of ARecordObject, which is a no-no.
Functional programmers don't just avoid mutation because it's a no-no (indeed, many functional programs make careful use of a controlled dose of mutability) - we do it because it produces safer, simpler code.
To wit: You're thinking in what I call "alloc-init mode", wherein you create some sort of "empty" value and then go about calculating its properties. Forgive my vehemency, but that's a fundamentally broken programming model, left over from the days of manual memory management; code which uses it will never be safe and abstractions relying on it will forever be leaky. The idiom doesn't fit into any language that's higher-level than C, and yet, if I had a pound for every time I see code like this...
var foo = new Foo();
foo.Bar = new Bar();
foo.Bar.Baz = new Baz();
...I would be a rich man (na na na). The default should be to create objects after you know what they're going to look like:
var foo = new Foo(new Bar(new Baz()));
This is simpler - you're just calculating a value, rather than reaching into the memory referenced by a pointer to update its contents - and more importantly it's safer because the type-checker ensures that you haven't forgotten a property and it allows you to make Foo immutable. The cleanest imperative code is functional code - you should only be imperative where necessary for performance (or when the language forces your hand).
Anyway, rant over. The point is that you're making life harder for yourself than necessary by thinking imperatively. Just write a function that calculates a single <li> from a single object...
toLi :: MyRecord -> HTML
toLi x = li [ id_ x.id, name_ x.name, class_ x.class ] [ text x.content ]
... (note that I'm not somehow creating an "empty" li and then populating its values), and then map it over your input list.
toLis :: [MyRecord] -> [HTML]
toLis = map toLi
This is how I'd do it in JS, too, even though I'm not required to by the language. No side-effects, no mutation, no need for Eff - just simple, safe, purely functional code.

Erlang: DRYing up string+binary concatenation

I am currently forming strings from strings and binaries like this:
X = string:join(io_lib:format("~s~s~s", ["something1", "something2",<<"something3">>]), "") %X is now something1something2something3
This seems painful and messy. Because in order to dry this up with another such string with a different number of "~n":
Y = string:join(io_lib:format("~s~s", ["something1", <<"something2">>]), "")
I essentially have to write a function that counts the size of the argument list, and forms ~n[that many times] and plugs it into this.
Is there a better way to be doing this?
Eshell V8.0.2 (abort with ^G)
1> F = <<"asdf">>,
1> string:join(io_lib:format("~s~s~s", ["something1", "something2", F]),"").
"something1something2asdf"
2> lists:flatten(["something1", "something2", F]).
[115,111,109,101,116,104,105,110,103,49,115,111,109,101,116,
104,105,110,103,50,<<"asdf">>]
3>
I'm confused as to why you need the call to io_lib:format at all. It's not doing any work in this case.
string:join(["something1","something2","something3"], "").
Would give you the same result. You can simplify even further if there's really no separator character (and taking advantage of the fact that strings are just lists in Erlang):
lists:flatten(["something1", "something2", "something3"]).
Update
I see now that you're working with a list of different data types. While a one-liner may look pretty, you can see that they're not always flexible. In your case, I would create some mapper functions to handle mapping different types to strings. Maybe something like:
-module(string_utils).
-export([concat/1]).
to_string(Value) when is_binary(Value) -> binary_to_list(Value);
to_string(Value) -> Value.
concat(List) ->
lists:flatten(lists:map(fun to_string/1, List)).
And then your calling code would be:
string_utils:concat(["something1", "something2", <<"something3">>]).

What's the best way to convert an Int to a String in Julia?

I am using Julia (version 0.4.6), and the method that I have tried is:
a = 123
println( string(Int(a))*"b" )
Which looks long and awkward.
The other way I have tried is to write it to a file, and then read it. This is clearly worse. I wonder if there is a recommended method.
I'm not sure what you're trying to accomplish with the *"b" in your syntax, but for the rest of it:
julia> a = 123
123
julia> string(a)
"123"
julia> println(a)
123
The string() function can also take more arguments:
julia> string(a, "b")
"123b"
Note that it is not necessary to convert an Int type to an ASCIIString before calling println() on it - the conversion will occur automatically.
You can also insert (aka interpolate) integers (and certain other types) into strings using $:
julia> MyString = "my integer is $a"
"my integer is 123"
Performance Tip: The above methods can be quite convenient at times. But, if you will be performing many, many such operations and you are concerned about execution speed of your code, the Julia performance guide recommends against this, and instead in favor of the below methods:
You can supply multiple arguments to print() and println() which will operate on them exactly as string() operates on multiple arguments:
julia> println(a, "b")
123b
Or, when writing to file, you can similarly use, e.g.
open("/path/to/MyFile.txt", "w") do file
println(file, a, "b", 13)
end
or
file = open("/path/to/MyFile.txt", "a")
println(file, a, "b", 13)
close(file)
These are faster because they avoid needing to first form a string from given pieces and then output it (either to the console display or a file) and instead just sequentially output the various pieces.
Note: Answer reflects updates based on helpful comment from #Fengyang Wang.

How to add only non-null item to a list in Groovy

I want to add non null items to a List. So I do this:
List<Foo> foos = []
Foo foo = makeFoo()
if (foo)
foos << foo
But is there a way to do it in a single operation (without using findAll after the creation of the list). Like:
foos.addNonNull(makeFoo())
Another alternative is to use a short circuit expression:
foo && foos << foo
The foo variable must evaluate to true for the second part to be evaluated. This is a common practice in some other languages but I'd hesitate to use it widely in groovy due to readability issues and conventions.
No, you'd need to use an if, or write your own addNonNull method (which just uses an if)
Also:
if( foo ) {
probably isn't enough, as this will skip empty strings, or 0 if it returns integers
You'd need
if( foo != null ) {
The answer is YES! we can get rid of assigning a variable
Foo foo = makeFoo()//we can ditch this
The answer is NO we can't get rid of the condition. BUT we can make it more compact.
Here's how
List<Foo> foos = []
foos += (makeFoo()?:[]);
The trick is groovy's "+" operator which works differently based on what is to the left and what is to the right of the "+". It just so happens that if what is on the left is a list and what is on the right is an empty list, nothing gets added to the list on the left.
Pros are it is quick to type and compact.
Cons are it is not instantly obvious what is happening to most people
AND we replaced the variable assignment with an extra operation. Groovy is
going to try to do something to List foos no matter what, it just so happens that in the second case the result of that operation gives us a desired result.

Groovy DSL: creating dynamic closures from Strings

There are some other questions on here that are similar but sufficiently different that I need to pose this as a fresh question:
I have created an empty class, lets call it Test. It doesn't have any properties or methods. I then iterate through a map of key/value pairs, dynamically creating properties named for the key and containing the value... like so:
def langMap = [:]
langMap.put("Zero",0)
langMap.put("One",1)
langMap.put("Two",2)
langMap.put("Three",3)
langMap.put("Four",4)
langMap.put("Five",5)
langMap.put("Six",6)
langMap.put("Seven",7)
langMap.put("Eight",8)
langMap.put("Nine",9)
langMap.each { key,val ->
Test.metaClass."${key}" = val
}
Now I can access these from a new method created like this:
Test.metaClass.twoPlusThree = { return Two + Three }
println test.twoPlusThree()
What I would like to do though, is dynamically load a set of instructions from a String, like "Two + Three", create a method on the fly to evaluate the result, and then iteratively repeat this process for however many strings containing expressions that I happen to have.
Questions:
a) First off, is there simply a better and more elegant way to do this (Based on the info I have given) ?
b) Assuming this path is viable, what is the syntax to dynamically construct this closure from a string, where the string references variable names valid only within a method on this class?
Thanks!
I think the correct answer depends on what you're actually trying to do. Can the input string be a more complicated expression, like '(Two + Six) / Four'?
If you want to allow more complex expressions, you may want to directly evaluate the string as a Groovy expression. Inside the GroovyConsole or a Groovy script, you can directly call evaluate, which will evaluate an expression in the context of that script:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
// Add each numer name as a property to the script.
numNames.eachWithIndex { name, i ->
this[name] = i
}
println evaluate('(Two + Six) / Four') // -> 2
If you are not in one of those script-friendly worlds, you can use the GroovyShell class:
def numNames = 'Zero One Two Three Four Five Six Seven Eight Nine'.split()
def langMap = [:]
numNames.eachWithIndex { name, i -> langMap[name] = i }
def shell = new GroovyShell(langMap as Binding)
println shell.evaluate('(Two + Six) / Four') // -> 2
But, be aware that using eval is very risky. If the input string is user-generated, i would not recommend you going this way; the user could input something like "rm -rf /".execute(), and, depending on the privileges of the script, erase everything from wherever that script is executed. You may first validate that the input string is "safe" (maybe checking it only contains known operators, whitespaces, parentheses and number names) but i don't know if that's safe enough.
Another alternative is defining your own mini-language for those expressions and then parsing them using something like ANTLR. But, again, this really depends on what you're trying to accomplish.

Resources