I have a list of stirings I need to manipulate and write out.
I get the strings the usual way with H|Tail recursion.
H will look something like "statement(foo, foo2, foo3, foo4, foo5)"
I want to be able to write out only foo, foo2, foo3 on separate lines
out: foo
bar: foo2
...
...
div: foo5
Convert string to codes, codes to a term, then destructure the term:
/* SWI Prolog
*/
read_from_string(String, Term) :-
string_to_list(String, List),
read_from_chars(List, Term).
demo:-
String="statement(foo, foo2, foo3,foo4,foo5)",
read_from_string(String, Term),
Term =.. [Fst,Snd,Thr|Rest],
write(functor:Fst),nl,
write(arg1:Snd),nl,
write(arg2:Thr),nl,
write(rest:Rest),nl.
Demo session:
?- demo.
functor:statement
arg1:foo
arg2:foo2
rest:[foo3,foo4,foo5]
true.
Choose the items to print according to their respective positions in the list that resulted from univ(=..). Here they were all printed.
Related
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.
I have a Maxima program that does some algebra and then writes some things down on an external file. How do I include some calculated values and even small expressions into the name of the file?
A mwe would be the following:
N:3;
f: erf(x);
tay: taylor(f,x,0,N);
with_stdout("taylor.txt", fortran(tay));
But this example names the file taylor.txt. I wanted something that named the file taylor_N3_f_erf.txt or something like that. I have tried several syntaxes but nothing worked.
Also, I know Maxima in programmed in lisp and I learned the syntax for concatenating strings in Lisp but I haven't figured out how to use that in Maxima.
Thank you very much.
Here's what I came up with. It took some playing around with argument quoting and evaluation in functions but I think it works now.
(%i2) bar (name_base, name_extension, ['vars]) := sconcat (name_base, foo(vars), ".", name_extension) $
(%i3) foo(l) := apply (sconcat, join (makelist ("_", 2 * length (l)), join (l, map (string, map (ev, l))))) $
(%i4) [a, b, c] : [123, '(x + 1), '(y/2)];
y
(%o4) [123, x + 1, -]
2
(%i5) bar ("foobar", "txt", a, b, c);
(%o5) foobar_a_123_b_x+1_c_y/2.txt
(%i6) myname : bar ("baz", "quux", a, b);
(%o6) baz_a_123_b_x+1.quux
(%i7) with_stdout (myname, print ("HELLO WORLD"));
(%o7) HELLO WORLD
(%i8) printfile ("baz_a_123_b_x+1.quux");
HELLO WORLD
(%o8) baz_a_123_b_x+1.quux
Note that sconcat concatenates strings and string produces a string representation of an expression.
Division expressions could cause trouble since / means a directory in a file name ... maybe you'll have to subsitute for those characters or any other non-allowed characters. See ssubst.
Note that with_stdout evaluates its first argument, so if you have a variable e.g. myname then the value of myname is the name of the output file.
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.
I am currently trying to create a (sort of) typesafe xml like syntax embedded into Haskell. In the end I am hoping to achieve something like this:
tree = group [arg1 "str", arg2 42]
[item [foo, bar] []
,item [foo, bar] []
]
where group and item are of kind Node :: [Arg t] -> [Node c] -> Node t. If this doesn't make any sense it is most probably because I have no idea what I am doing :)
My question now is how to make the type system prevent me from giving 'wrong' arguments to a Node. Eg Nodes of type Group only may have arguments of type Arg1 and Arg2 but Items may have arguments of type Foo and Bar.
I guess the bottom line question is: how do i restrict the types in a heterogenous list?
Example of the (user) syntax i am trying to achieve:
group .: arg1 "str" .: arg2 42
item .: foo .: bar
item .: foo .: bar
where (.:) is a function that sets the parameter in the node. This would represent a group with some parameters containing two items.
Additionally there would be some (pseudo) definition like:
data Node = Node PossibleArguments PossibleChildNodes
type Group = Node [Arg1, Arg2] [Item]
type Item = Node [Foo, Bar] []
I am searching for a way to catch usage errors by the typechecker.
What you have doesn't sound to me like you need a heterogeneous list. Maybe you're looking for something like this?
data Foo = Foo Int
data Bar = Bar Int
data Arg = StringArg String | IntArg Int | DoubleArg Double
data Tree = Group Arg Arg [Item]
data Item = Item Foo Bar
example :: Tree
example = Group (StringArg "str") (IntArg 42)
[Item (Foo 1) (Bar 2), Item (Foo 12) (Bar 36)]
Note that we could even create a list of Args of different "sub-types". For example, [StringArg "hello", IntArg 3, DoubleArg 12.0]. It would still be a homogeneous list, though.
===== EDIT =====
There are a few ways you could handle the "default argument" situation. Suppose the Bar argument in an item is optional. My first thought is that while it may be optional for the user to specify it, when I store the data I want to include the default argument. That way,
determining a default is separated from the code that actually does something with it. So,
if the user specifies a Foo of 3, but doesn't supply a Bar, and the default is Bar 77, then I create my item as:
Item (Foo 3) (Bar 77)
This has the advantage that functions that operate on this object don't need to worry about defaults; both parameters will always be present as far as they are concerned.
However, if you really want to omit the default arguments in your data structure, you could do somthing like this:
data Bar = Bar Int | DefaultBar
example = Group (StringArg "str") (IntArg 42)
[Item (Foo 1) (Bar 2), Item (Foo 12) DefaultBar]
Or even:
data Item = Item Foo Bar | ItemWithDefaultBar Foo
===== Edit #2 =====
So perhaps you could use something like this:
data ComplicatedItem = ComplicatedItem
{
location :: (Double, Double),
size :: Int,
rotation :: Double,
. . . and so on . . .
}
defaultComplicatedItem = ComplicatedItem { location = (0.0,0.0), size = 1, rotation = 0.0), ... }
To create a ComplicatedItem, the user only has to specify the non-default parameters:
myComplicatedItem = defaultComplicatedItem { size=3 }
If you add new paramters to the ComplicatedItem type, you need to update defaultComplicatedItem, but the definition for myComplicatedItem doesn't change.
You could also override the show function so that it omits the default parameters when printing.
Based on the ensuing discussion, it sounds like what you want is to create a DSL (Domain-Specific Language) to represent XML.
One option is to embed your DSL in Haskell so it can appear in Haskell source code. In general, you can do this by defining the types you need, and providing a set of functions to work with those types. It sounds like this is what you're hoping to do. However, as an embedded DSL, it will be subject to some constraints, and this is the problem you're encountering. Perhaps there is a clever trick to do what you want, maybe something involving type functions, but I can't think of anything at present. If you want to keep trying, maybe add the tags dsl and gadt to your question, catch the attention of people who know more about this stuff than I do. Alternatively, you might be able to use something like Template Haskell or Scrap Your Boilerplate to allow your users to omit some information, which would them be "filled in" before Haskell "sees" it.
Another option is to have an external DSL, which you parse using Haskell. You could define a DSL, but maybe it would be easier to just use XML directly with a suitable DTD. There are Haskell libraries for parsing XML, of course.
I'm a bit new to Groovy, so I'm sure this is one of those extremely obvious things...but it's difficult to search for via Google.
In other languages, asterisks tend to represent pointers. However, in this snippet of Groovy code:
byte[] combineArrays(foo, bar, int start) {
[*foo[0..<start], *bar, *foo[start..<foo.size()]]
}
I can only imagine that that's not the case. I mean, pointers? Groovy?
I'm assuming that this code intends to pass the members of foo and bar as opposed to a multidimensional array. So what exactly do the asterisks mean?
Thanks a lot for your help.
When used like this, the * operator spreads a List or Array into a list of arguments. That didn't help at all, did it? How about an example instead? Say we have this function:
def add(Number a, Number b) {
return a + b
}
And this List
def args = [1, 2]
We shouldn't do this:
add(args)
because the function expects two numeric arguments. But we can do this:
add(*args)
because the * operator converts the List of 2 elements into 2 arguments. You can use this operator with Lists and Arrays.