Does Hy code require indenting, just like Python? - hy

I am unable to submit multiple lines of Hy to Python without indentation:
import hy
expr=hy.read_str("(+ 1 1)(+ 2 2)")
hy.eval(expr)
=> 2
The second '(+ 2 2)' statement has apparently been ignored.
Obviously Python's raison d'etre is indentation, and of course the 'Hy Style Guide" shows everything constantly indented, and has this to say as well:
"New lines must ALWAYS be indented past their parent opening bracket."
So is there no way to avoid indentation in Hy and to submit a single, non-indented string via hy.eval(expr)?

Hy is a free-form language, like most programming languages and unlike Python. The style guide is only a style guide.
What you're seeing with read-str is issue #1591. Use do to combine multiple expressions into one.

No, indentation is not required in Hy, and (as Kodiologist notes) the Hy Style Guide's endless prattling on about indentation is, as it should be, nothing more than a suggestion.
However Hy does not have any sort of 'compound expression'-type of form, and the submission of a sequence of multiple statements to Hy does require additional tricks.
The obvious solution, to make submit multiple statements (aka 'forms') as a sequence does NOT work:
hy.eval(hy.read_str( "((+ 1 1) (+ 2 2))" ))
-> TypeError: 'int' object is not callable
Which occurs of course because Hy is trying to 'call' the number 2 as a function on the number 4.
One can collect sequences of forms in a list. However this captures all of their outputs:
hy.eval(hy.read_str( "[(+ 1 1) (+ 2 2)]" ))
-> [ 2 4 ]
Naturally for a very large computation with many steps it is possible to end up with a list of junk that one does not need, wasting memory. (However most Hy forms resolve to 'None' which is pretty small). So one can just wrap everything with a 'last' statement:
hy.eval(hy.read_str( "(last [(+ 1 1) (+ 2 2) (+ 3 3)] )" ))
-> 6
Probably the best solution is to use do as Kodiologist notes:
hy.eval(hy.read_str( "(do (+ 1 1) (+ 2 2) (+ 3 3) )" ))
-> 6

Related

local scopes in Julia

I understand that the for loops are now local in Julia. But there is something I do not understand. Please consider the following two examples.
Example 1
a = 0
for i = 1:3
a += 1
end
Example 2
a = [0]
for i = 1:3
a[1] += 1
end
Example 1 throws an error message, which I understand. But Example 2 works as it is expected. How should I understand this? Arrays are not variables? Can somebody explain this to me?
This question is essentially a duplicate of Julia scoping: why does this function modify a global variable?, where it is discussed in detail that the difference is that a = ... is an assignment operation (changes binding of a variable a) and a[1] = ... is a setindex! operation (changes value contained in a collection). Also see Creating copies in Julia with = operator.
I am not marking it as a duplicate only because in your case the first example fails in REPL under Julia 1.4.2 but will work under Julia 1.5 once it is released, see https://github.com/JuliaLang/julia/blob/v1.5.0-rc1/NEWS.md:
The interactive REPL now uses "soft scope" for top-level expressions: an assignment inside a scope block such as a for loop automatically assigns to a global variable if one has been defined already. This matches the behavior of Julia versions 0.6 and prior, as well as IJulia. Note that this only affects expressions interactively typed or pasted directly into the default REPL (#28789, #33864).

Is there any functional difference between Array.replicate and Array.create in F#?

I was refactoring some code and noted that some coders used Array.replicate and other Array.create when initializing an array with repeatedly the same value. The signatures of both functions are identical:
> Array.create;;
val it : (int -> 'a -> 'a [])
> Array.replicate;;
val it : (int -> 'a -> 'a [])
I also noted that both raise an ArgumentException on a negative count value, and both allow a count of zero. My gut tells me they are synonymous, but then I found this quote on F# For Fun And Profit:
Array.create is basically the same as replicate (although with a subtly different implementation!) but replicate was only implemented for Array in F# v4.
Is anybody aware of what differences exist, or are they, for all intents and purposes, aliases of one another (perhaps replicate was merely added for parity with seq)?
The code is equivalent and shouldn't perform any differently.
It seems like it was added to Seq and Array after List, so maybe for API parity. This is an old commit (2014) and a quick search through issues didn't turn out any one that would definitely explain the reasons for the change. https://github.com/dotnet/fsharp/commit/173d833660767fd24d523d09f317179cc3c3f4b9

Multi-line inputs in RIDE (APL)?

I wish to type in a multi-line array as follows:
ast ← ('∘'
('a' ('p'))
('b'
('q' ('v'))
('r'))
('c'
('s' ('w' 'x'))
('t' ('y' 'z'))))
This is correctly paranthesized, but I am unable to copy-paste it into the Dyalog APL RIDE interface. I searched around, and found two answers both of which do not help me:
A github issue: Unable to paste any DFN from dfns website asks about pasting DFNS, which explains that one can use ∇. When I type the ∇, the UI of the text-box changes and becomes dark gray, which is encouraging, but on typing ast ← { <ENTER> or ast ← ( <ENTER> it errors out.
This SO question on multi-line text values in APL asks how to input text. I tried to use the { } method, but when I type ast ← { <ENTER> it already errors out.
So, how does one type multiline data in APL?
The session doesn't currently support multi line arrays.
For now, you still have to create multi dimensional arrays programmatically for the most part (although you can, for example, create an editable text matrix, fill it with "numbers" and then use ⍎¨)
cmat←⍪''
)ed cmat
paste this
0123
2314
1244
then fix it (press Esc) and use
⍎¨cmat
For me, I find Shift-Enter and Ctrl-Enter are my best friends most of the time
It looks like you're trying to represent a tree as a nested array (look at dfns tview and tnest and other tree stuff for more on that). As such, it doesn't look like you really need multiline (all arrays in APL are hyperrectangular)?
ast←('∘'('a' ('p'))('b'('q'('v'))('r'))('c'('s' ('w' 'x'))('t' ('y' 'z'))))
Traditional functions (tradfns) can be copy and pasted readily, if they use the session input format:
∇ r ← larg Fun rarg
r ← larg, rarg
∇
Multi-line dfns can be pasted. First use the ]dinput user command.
]dinput
then paste
dfn ← {
⍺, ⍵
}
(btw, regarding ∇ from the previous comment, you can paste the multiline dfn and prepend with ∇, but you have to put ∇ on the last line [n] and press enter for it to fix the function. The ]dinput user command is a bit simpler)
In addition to Richard Park's excellent answer, it should be noted that Dyalog is working on multi-line arrays on two fronts:
Designing a new multi-line array notation
The newest edition was presented in 2018
⎕SE.Link.Serialise can create multi-line notation from most any array
⎕SE.Link.Deserialise will return the array specified by its argument notation array
Multi-line session input
Version 18.0 (due summer 2020) includes experimental multi-line session support. It has to be enabled with a configuration parameter.
It will detect unfinished dfns (e.g. MyFn←{ and 4{) and control structures (e.g. :If myVar>5 and :Class MyCl) but not array notation.
18.0 will also contain a tool, ⎕SE.Link.Array which allows wrapping multi-line array notation in a dfn:
{
[1 2 3
4 5 6]
}⎕SE.Link.Array⍬

Pretty printing with Sagemath command line

How do I "pretty-print" something in the Sagemath command line (as in sympy)? The only solution I found was to use get_test_shell() function, according to this entry in the docs. But basically I have to use
from sage.repl.interpreter import get_test_shell
shell = get_test_shell()
shell.run_cell('%display ascii_art')
shell.run_cell('integral(x^2/pi^x, x)')
I find this to be too cumbersome (4 complicated lines just to display things nicely!) and what you want to display even has to be given as a string. So I'm looking for an easier alternative. I'm sure there's another way; I just can't find it.
I think I might be using the wrong terms because according to the manual itself:
Pretty printing means
rendering things so that MathJax or some other latex-aware front end
can render real math.
So if I use pretty_print_default(True) it's going to always print latex, which isn't what I want for now.
One thing I tried that I thought would work was to do
from sympy import pretty_print
Which should use Sympy's pretty-print (which is what I actually want), but it doesn't make any difference.
You ran across the problem that we want to be able to doctest things that are interactive by their nature. Try just this at the command line:
sage: %display ascii_art
sage: integral(x^2/pi^x, x)
/ 2 2 \ -x*log(pi)
-\x *log (pi) + 2*x*log(pi) + 2/*e
---------------------------------------------
3
log (pi)
This is one of the "magic" percent directives in IPython. I agree it could be documented better.

Is there YAML syntax for sharing part of a list or map?

So, I know I can do something like this:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
And have sitelist and anotherlist both contain www.foo.com and www.bar.com. However, what I really want is for anotherlist to also contain www.baz.com, without having to repeat www.foo.com and www.baz.com.
Doing this gives me a syntax error in the YAML parser:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist: *sites
- www.baz.com
Just using anchors and aliases it doesn't seem possible to do what I want without adding another level of substructure, such as:
sitelist: &sites
- www.foo.com
- www.bar.com
anotherlist:
- *sites
- www.baz.com
Which means the consumer of this YAML file has to be aware of it.
Is there a pure YAML way of doing something like this? Or will I have to use some post-YAML processing, such as implementing variable substitution or auto-lifting of certain kinds of substructure? I'm already doing that kind of post-processing to handle a couple of other use-cases, so I'm not totally averse to it. But my YAML files are going to be written by humans, not machine generated, so I would like to minimise the number of rules that need to be memorised by my users on top of standard YAML syntax.
I'd also like to be able to do the analogous thing with maps:
namedsites: &sites
Foo: www.foo.com
Bar: www.bar.com
moresites: *sites
Baz: www.baz.com
I've had a search through the YAML spec, and couldn't find anything, so I suspect the answer is just "no you can't do this". But if anyone has any ideas that would be great.
EDIT: Since there have been no answers, I'm presuming that no one has spotted anything I haven't in the YAML spec and that this can't be done at the YAML layer. So I'm opening up the question to idea for post-processing the YAML to help with this, in case anyone finds this question in future.
The merge key type is probably what you want. It uses a special << mapping key to indicate merges, allowing an alias to a mapping (or a sequence of such aliases) to be used as an initializer to merge into a single mapping. Additionally, you can still explicitly override values, or add more that weren't present in the merge list.
It's important to note that it works with mappings, not sequences as your first example. This makes sense when you think about it, and your example looks like it probably doesn't need to be sequential anyway. Simply changing your sequence values to mapping keys should do the trick, as in the following (untested) example:
sitelist: &sites
? www.foo.com # "www.foo.com" is the key, the value is null
? www.bar.com
anotherlist:
<< : *sites # merge *sites into this mapping
? www.baz.com # add extra stuff
Some things to notice. Firstly, since << is a key, it can only be specified once per node. Secondly, when using a sequence as the value, the order is significant. This doesn't matter in the example here, since there aren't associated values, but it's worth being aware.
As the previous answers have pointed out, there is no built-in support for extending lists in YAML. I am offering yet another way to implement it yourself. Consider this:
defaults: &defaults
sites:
- www.foo.com
- www.bar.com
setup1:
<<: *defaults
sites+:
- www.baz.com
This will be processed into:
defaults:
sites:
- www.foo.com
- www.bar.com
setup1:
sites:
- www.foo.com
- www.bar.com
- www.baz.com
The idea is to merge the contents of a key ending with a '+' to the corresponding key without a '+'. I implemented this in Python and published here.
(Answering my own question in case the solution I'm using is useful for anyone who searches for this in future)
With no pure-YAML way to do this, I'm going to implement this as a "syntax transformation" sitting between the YAML parser and the code that actually uses the configuration file. So my core application doesn't have to worry at all about any human-friendly redundancy-avoidance measures, and can just act directly on the resulting structures.
The structure I'm going to use looks like this:
foo:
MERGE:
- - a
- b
- c
- - 1
- 2
- 3
Which would be transformed to the equivalent of:
foo:
- a
- b
- c
- 1
- 2
- 3
Or, with maps:
foo:
MERGE:
- fork: a
spoon: b
knife: c
- cup: 1
mug: 2
glass: 3
Would be transformed to:
foo:
fork: a
spoon: b
knife: c
cup: 1
mug: 2
glass: 3
More formally, after calling the YAML parser to get native objects from a config file, but before passing the objects to the rest of the application, my application will walk the object graph looking for mappings containing the single key MERGE. The value associated with MERGE must be either a list of lists, or a list of maps; any other substructure is an error.
In the list-of-lists case, the entire map containing MERGE will be replaced by the child lists concatenated together in the order they appeared.
In the list-of-maps case, the entire map containing MERGE will be replaced by a single map containing all of the key/value pairs in the child maps. Where there is overlap in the keys, the value from the child map occurring last in the MERGE list will be used.
The examples given above are not that useful, since you could have just written the structure you wanted directly. It's more likely to appear as:
foo:
MERGE:
- *salt
- *pepper
Allowing you to create a list or map containing everything in nodes salt and pepper being used elsewhere.
(I keep giving that foo: outer map to show that MERGE must be the only key in its mapping, which means that MERGE cannot appear as a top-level name unless there are no other top level names)
To clarify something from the two answers here, this is not supported directly in YAML for lists (but it is supported for dictionaries, see kittemon's answer).
To piggyback off of Kittemon's answer, note that you can create mappings with null values using the alternative syntax
foo:
<< : myanchor
bar:
baz:
instead of the suggested syntax
foo:
<< : myanchor
? bar
? baz
Like Kittemon's suggestion, this will allow you to use references to anchors within the mapping and avoid the sequence issue. I found myself needing to do this after discovering that the Symfony Yaml component v2.4.4 doesn't recorgnize the ? bar syntax.

Resources