Not in Lisp! ("foo" "bar") and ("foobar") are lists of length 2 and 1, respectively.
(Python copies some bad ideas from C. Another one is having to import everything you use. It seems that since Python is written in C, its designer took it for granted that there will be something analogous to #include for using libraries, even standard ones that come with the language.)
Implicit string literal catenation is tempting to implement because it solves problems like:
and if you're working in a language which has comma separation everywhere, you can get away with it easily.
There are other ways to solve it. In TXR Lisp, I allow string literals to go across multiple lines with a backslash newline sequence. All contiguous unescaped whitespace adjacent to the backslash is eaten:
This is the TXR Lisp interactive listener of TXR 273.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
TXR needs money, so even abnormal exits now go through the gift shop.
1> "abcd \
efg"
"abcdefg"
If you want a significant space, you can backslash escape it; the exact placement is up to you:
I like imports, it tells me what files symbols are coming from, even for built in libraries.
Maybe it is that through my work I use a half dozen languages, where it is hard to remember each in detail.
I have also worked on a javascript project where there were no imports/requires and the build process created one file. So you had to inspect the confusing build script to even know what was what.
And especially how I can choose the best way to indicate the sources of names in my code:
import time
t = time.perf_counter()
import time, my_module
t1 = time.perf_counter()
t2 = my_module.perf_counter()
from time import perf_counter as std_counter
from my_module import perf_counter as my_counter
t1 = std_counter()
t2 = my_counter()
try:
from my_module import perf_counter
except ImportError:
# Fall back to standard implementation
from time import perf_counter
t = perf_counter()
# import time as m
import my_module as m
t = m.perf_counter()
long %s stringnicely breaks upwith indentation and all"
? In my experience, this always gets ugly when you want to insert spaces (= about always). Do you put them at the end or at the start of each string (apart from the first or last string)
I think scala’s mkString (https://superruzafa.github.io/visual-scala-reference/mkStrin...) is the best solution, visually, for such things, but unfortunately, it would require hackers in the parser to do the concatenation at compile time, where possible.
The spaces aren't the point of the comment; rather that we can break the literal into pieces and indent those pieces without affecting the contents. In a non-strawman real exmaple with real data, of course we include all the necessary spaces in the literals. However, this bug is easy to make in C; I've seen it numerous times.
I don't know of a good design that won't lead you to make errors when you don't want the spaces. You'd need some piece of syntax which indicates whether you
want a space there or not. For instance, there could be a rule that a string
literal ending in non-whitespace cannot joined with a literal starting with non-whitespace:
"foo" "bar" // error
"foo " "bar" // OK
"foo" " bar" // OK
"foo" "" "bar" // OK: "" doesn't start with non-whitespace, since it's empty
"foo" " " "bar" // OK
The nice thing about this is that it's perfectly comatible with existing C.
All we have to do is to implement a compiler warning which detects when the rule is violated.
Users who implement it have to fix situations like "foo" "bar" into "foo" "" "bar".
Probably the rules should be smarter. Some kind of tokenization concept could be at play
so that gluing together two letters or digits is bad, or two punctuation tokens, but
letter/number and punctuation is okay.
> Another one is having to import everything you use.
The alternative is what exactly? Have the entire standard library exposed at once? Make all modules create non-conflicting names for exported objects, so that the json parse function has to be called json_parse and the csv parse function has to be called csv_parse?
It lets you debug. E.g. if they have made a file called cvs.py in the same directory, then print (cvs.__file__) will show you this. If they have some weirdly screwed up paths with multiple pythons installed and multiple copies of the modules etc., same.
I will not Go lang has the same feature carried forward from C. It helps a lot in the reading code side of the code lifecycle. And Go compiler makes you keep the imports up to date, which is good.
It lets you debug Python problems which the system created in the first place.
> If they have some weirdly screwed up paths with multiple pythons installed and multiple copies of the modules etc., same.
Doesn't happen in a sane language. Or, even not a sanely defined language/implementation.
I can easily have multiple different GCC copies (possibly for different processor targets) on the same machine. Each one knows where its own files are; an #include <stdio.h> compiled with your /path/to/arm-linux-eabi-gcc will positively not use your /usr/include/stdio.h, unless you explicitly do stupid things, like -I/usr/include on the command line.
It can be slightly inconvenient but doesn’t feel moronic to me. It means that except for the built-in functions, everything can be traced to either a definition or an import. Makes tracking code much easier.
Why not import the built-in functions too? The only thing not requiring import can be import.
from python import def # now you can def
That should be even easier to track things; now you don't have to deal with the difficulty of def not being defined anywhere in your code. It's traced to an import, which is telling you that def comes from python, liberating you from having to know that and remember it.
@"
here strings in PS are fine for this purpose and
even allows whitespace anywhere
but because of the latter you can't indent it
with your other code
"@ -split "`r`n" | % {'<SOL>{0}<EOL>' -f $_ }
<SOL> here strings in PS are fine for this purpose and <EOL>
<SOL> even allows whitespace anywhere <EOL>
<SOL> but because of the latter you can't indent it <EOL>
<SOL> with your other code <EOL>
Having everything be imported is what makes the language be useable. Especially if you never import * you can easily find the definition and meaning of everything you read on the screen. A prime example of explicit is better than implicit.
And backslash doesn’t let you have the literal obey the proper indenting. Might as well use “””
> you can easily find the definition and meaning of everything you read on the screen
I don't want to be finding definitions of things that the language provides in the code.
Languages that don't work this way have IDE's, editor plug-ins or other tools for easily finding the definitions of things that are in the language, without hunting for them through intermediate definition steps in the same file.
"I've spent all my life in and out of jails, so I expect bars on doors and windows ..."
I'm gonna disagree on the import thing. Compared to Ruby where requires are magic bags of metaprogramming bullshit, Python is much much easier to reason about. It takes some getting used to that require 'json' actually adds methods to existing classes.
I mean, I understand that classes which are open to extension with new methods is useful, and the right way to do OOP and all.
If it was CLOS with multiple dispatch, it would be easier to swallow. Because it would look like:
(to-json { hello: "world" })
;; error: no such function!
Then load the module, and you have a generic to-json function now, with a method specialized to handle the dictionary object and all. (I still wouldn't want to be doing this if it's supposed to be a language built-in).
I regard the ability to add new methods to a class as good, but with a valid use case, like extending some third party piece with new methods in your own application. And the fact of not having to declare methods in a class definition, which is cumbersome. Just write a new method in that class's file, at the bottom, and there it is.
I ideally don't want that third-party piece itself to be divided into three pieces that I have to separately load to get all of the methods. Or worse, pieces from separate third parties that add methods to each other.
I copied a thing or two from Ruby in TXR Lisp. The object system as a derived hook, and that was inspired by something in Ruby:
The derived hook is inherited (like any other static slot), so it fires in bar also. The function can distinguish which class is being derived by the super argument.
Interesting. Arguably tho this shows how C is aging. I find that PRIx32 a bit ugly.
Although I just had a (logging) use case in go where I missed cpp macros - wanted the log statement to get something from the file and just had to pass it in as another parameter.
I have also never used PRI-anything. It's a crime against readability.
If I have a uint32_t which needs printing I cast it to (unsigned long) and use %lu or %lx. This requires more typing in the argument list, but keeps the format string tidy. It's important for the format string to be tidy, because that's the reason of its existence: to clearly and concisely convey the shape of what is being printed.
> I meant that “abc” + “def” is most likely illegal
That would be adding 2 pointers, and that's indeed illegal.
However, you can subtract them: “abc” - “def” . Now, the result is not a pointer any more, it's a ptrdiff_t (an integer type), so most compilers will warn if you try to assign that to a char *.
Because the parent compared Python's behavior to that of C. The difference of course is that adding strings doesn't make sense in C, so there's no danger of misinterpreting "abc" "def" in C, as there is in Python.
(Python copies some bad ideas from C. Another one is having to import everything you use. It seems that since Python is written in C, its designer took it for granted that there will be something analogous to #include for using libraries, even standard ones that come with the language.)
Implicit string literal catenation is tempting to implement because it solves problems like:
and if you're working in a language which has comma separation everywhere, you can get away with it easily.There are other ways to solve it. In TXR Lisp, I allow string literals to go across multiple lines with a backslash newline sequence. All contiguous unescaped whitespace adjacent to the backslash is eaten:
If you want a significant space, you can backslash escape it; the exact placement is up to you: