7 ms·
Go enjoy Python3
- deleted 11y ago[deleted]
- masklinn 11y ago> Simple enough, in essence given first argument, print it up to length 12. As an added this also deals with unicode correctly That's not true, Python 3 uses codepoint-based indexing but it will break if combining characters are involved. For instance: > python3 test.py देवनागरीदेवनागरी देवनागरीदेवन because there is no precombined version of the multi-codepoint grapheme clusters so some of these 10 user-visible characters takes more than a single you end up with 8 user-visible characters rather than the expected 10. edit: the original version used the input string "ǎěǐǒǔa̐e̐i̐o̐u̐ȃȇȋȏȗ" where clusters turn out to have precomposed versions after all. Replaced it by devanāgarī repeated once (in the devanāgarī script)
- Veedrac 11y agoThe easy Python way: import sys import regex print(regex.match("\X{,12}", sys.argv[1]).group()) with the regex[1] package that should be in the stdlib Any Day Now™. [1]: https://pypi.python.org/pypi/regex https://pypi.python.org/pypi/regex
- Spiritus 11y agoInteresting, I had no idea the `re` module was getting revamped. Scheduled for 3.5 or later?
- Veedrac 11y agoCertainly not 3.5, although a few years ago I would have told you almost the exact opposite. I wouldn't hold your breath. The issue tracker[1] suggests 3.7 or 3.8 as optimistic. Guido made some comment somewhere relatively recently, but I can't find where. It's entirely possible it will never actually happen; time doesn't seem to have made people more enthusiastic. It's a shame, because the new module is awesome. [1] http://bugs.python.org/msg230846 http://bugs.python.org/msg230846
- hahainternet 11y agoThat's a shame, it works as you'd expect in perl6: sub MAIN($s) { say $s.substr(0,12) } $ perl6 test.p6 ǎěǐǒǔa̐e̐i̐o̐u̐ȃȇȋȏȗ ǎěǐǒǔa̐e̐i̐o̐u̐ȃȇ
- deleted 11y ago[deleted]
- masklinn 11y agoTurns out there are precomposed versions of these clusters, so your system might just be using these. Could you retry with the input "देवनागरीदेवनागरी"?
- hahainternet 11y agoI'm not quite sure how to interpret the output as it doesn't render particularly kindly in my terminal: sub MAIN($s) { say "{$s.chars}: $s"; my $b = $s.substr(0,12); say "{$b.chars}: $b"; } $ perl6 hn-test2.p6 देवनागरीदेवनागरी 16: देवनागरीदेवनागरी 12: देवनागरीदेवन
- masklinn 11y agoSo apparently perl6 is also "wrong" and operates on codepoints, your system composed my original string and each (base, diacritic) pair was pasted as a single precomposed character (I expect that if you try out the Python version on your system you'll also get the "right" answer). The new string is composed of 10 user-visible characters (5 character repeated twice) but 16 codepoints (and this time I carefully checked that there was no precomposed version): DEVANAGARI LETTER DA DEVANAGARI VOWEL SIGN E DEVANAGARI LETTER VA DEVANAGARI LETTER NA DEVANAGARI VOWEL SIGN AA DEVANAGARI LETTER GA DEVANAGARI LETTER RA DEVANAGARI VOWEL SIGN II DEVANAGARI LETTER DA DEVANAGARI VOWEL SIGN E DEVANAGARI LETTER VA DEVANAGARI LETTER NA DEVANAGARI VOWEL SIGN AA DEVANAGARI LETTER GA DEVANAGARI LETTER RA DEVANAGARI VOWEL SIGN II Operating on codepoints, both versions cut after the second DEVANAGARI LETTER NA (न) breaking that grapheme cluster (it should be ना) and not displaying the final two clusters ग and री.
- bmn_ 11y agoLanguages that cannot deal with graphemes are lame. I daresay this solution below should score 20 in OP's imaginary scale. $ perl -CADS -E'say $ARGV[0] =~ /(\X{5})/' देवनागरीदेवनागरी देवनागरी Length of input string is: 10 graphemes, 16 codepoints, 48 octets (UTF-8). Length of output string is: 5 graphemes, 8 codepoints, 24 octets (UTF-8).
- stevenbedrick 11y agoYup. A long time ago, while working on a project with some particularly gnarly Unicode issues, I got in the habit of thinking in terms of grapheme clusters instead of code points (or "characters", for whatever definition of "character" one wishes to use), and it has served me very well. Combining characters pop up in the most interesting places, often where and when you least expect them! ٩(•̃̾●̮̮̃̾•̃̾)۶ Ruby's unicode_utils gem has a nice implementation of the standard grapheme cluster segmentation algorithm, and Python's wrapper around ICU works quite well. Go's concept of runes is certainly an improvement, but it doesn't handle combining characters out of the box...
- masklinn 11y ago> Combining characters pop up in the most interesting places, often where and when you least expect them! ٩(•̃̾●̮̮̃̾•̃̾)۶ The good news is Unicode 8 will make them way more frequent! (alternate emoji skin colors are specified via combining characters) much as Unicode 6 made astral characters way more "in your face" (by standardising emoji in the SMP)
- crawshaw 11y agoThere are several ways to solve this in Go. The first that comes to mind, assuming you want to truncate to the first 12 runes, not bytes: func main() { v := []rune(os.Args[1]) if len(v) > 12 { v = v[:12] } fmt.Println(string(v)) } Or more in the spirit of the C example in the post: func main() { res := make([]rune, 12) copy(res, []rune(os.Args[1])) fmt.Println(string(res)) } Note that res will stay on the stack, just like C. I expect the author is trying to say something about Go that I'm not quite getting. Perhaps that it is not an expression-based language, so to make code readable you need to make use of multiple statements. That's by design, but I understand it may be unappealing if you want to program in an expression-heavy style.
- jerf 11y ago"I expect the author is trying to say something about Go that I'm not quite getting." I assume "Go sucks because, look, this one weird case is a bit ugly." (that is, as rhetoric, not dialectic; it is not literally claiming "one case bad" -> "Go is bad" in the logical sense.) A weird case that I've programmed many thousands of lines of Go code in but never once encountered. Taking a slice out of a string blind like that is actually a bit rare; usually in some way it turns out you actually have length information somewhere in the environment. It's hardly like "slice index out of bounds" is some sort of terrible error... it is, at least, arguable that Python is in the wrong here for being so willing to return a string generated by [0:12] that is not 12 bytes/characters in length, which seems like a reasonable assumption to make of such an operation. Now, if we want to talk about little examples like this, let's talk about sending on something like a channel in Python, to say nothing of Python's implementation of the "go" keyword... oh, yes, I see, suddenly this is an unfair way to compare languages. Yes, it is.
- bsaul 11y agoThis posts shows two very common issues that programmer have with the GO language when they start using it (that includes me), especially since go is advertised as compiled with the feeling of a dynamic language : A low-level feeling when manipulating arrays (or slice), and a poor support for generic functions ( that would be math.min in this example).
- deleted 11y ago[deleted]
- Sir_Cmpwn 11y agoThe C code there fails if the unicode string includes characters whose width is greater than one octet.
- zokier 11y agoWhich is noted right in the post: > This treats things as byte-array instead of unicode, thus for unicode test it will end up printing just 車賈滑豈.
- rakoo 11y agoWhich is useless then, because the output can't safely be considered a string anymore. I don't really see the point of writing the C "equivalent" and giving it any point when it doesn't even do the right thing.
- masklinn 11y agoNone of the snippets comes even remotely close to doing the right thing so it doesn't really matter.
- _pmf_ 11y agoOf course, the C version could be just printf("(%.12s)\n", argv[1]);
- pjmlp 11y agoAssuming using 7 bit ASCII
- _kst_ 11y agoNo, it merely assumes one byte per character. For example, it would work correctly in Latin-1 or EBCDIC. In any case, the problem statement (though it's a bit vague) requires building a truncated string, not just printing it.
- kevin_thibedeau 11y agos/printf/sprintf/
- pjmlp 11y agoIt is enough to have mixed 8 byte code pages and then it is worthless.
- chapium 11y agoCompletely off topic, so if you are looking for discussion about the article skip this. The low contrast ratio and bright colors on this blog are a bit hard to read. I normally switch to readability mode in safari when I encounter this, but the sites layout prevents this from working.
- jofer 11y agoThe text is black on white... Am I missing something?
- BinaryIdiot 11y agoHmm, are you referring to something very specific? The contrast ratio is incredibly high (black text on white background). The navigation bar has terrible contrast but that's all I saw.
- IshKebab 11y agoNow try distributing your Python code as a single statically linked exe.
- PyComfy 11y agohttp://nuitka.net/pages/overview.html http://nuitka.net/pages/overview.html
- Skunkleton 11y agoHow is this on the front page of hacker news? What a shit post.
- Daishiman 11y agoThe Unicode situation in most languages is dismal. Honestly though, the lack of generics for that Math.min function makes me happy I'm not programming in Go.
- insertnickname 11y agoif a > b { // use a } else { // use b }
- ridiculous_fish 11y agoOh dear. You had one job, min!
- insertnickname 11y agoYeah, I was thinking of max, not min, sorry. My point was that it's a trivial thing to write, your generic max (or min) is right there. The math.Max() (and math.Min()) function is not trivial, it handles certain special cases, and that's probably why it was included.[1] [1] https://golang.org/pkg/math/#Max https://golang.org/pkg/math/#Max
- Veedrac 11y agoThat's actually the wrong way around.
- insertnickname 11y agoYeah, I was thinking of max, not min, sorry. My point was that it's a trivial thing to write, your generic max (or min) is right there. The math.Max() (and math.Min()) function is not trivial, it handles certain special cases, and that's probably why it was included.[1] [1] https://golang.org/pkg/math/#Max https://golang.org/pkg/math/#Max
- jackielii 11y agowhy can't I downvote this!!! erhhhh
- flohofwoe 11y agoDoesn't the C version have a serious bug? If the input string has 12 or more characters, the destination string will not be zero-terminated. From the strncpy docs: "No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow)."
- ansible 11y agoI'm usually sticking +1s to the storage for any strings for this purpose. So if I want to operate on MAXLEN number of characters, I'll allocation MAXLEN+1 for the character array. And often times I'll be memset()'ing the destination to all NULLs when doing a string copy operation. I'm not real happy with string handling in C... as if that should be surprising to anyone. Say, is there nice, small, suitable for embedded use string library anyone would care to recommend in C? I just want a nice string type that carries around its length and storage length, handles copies properly, and has the usual utilities. I suppose I could just write one...
- _kst_ 11y agoThere are at least three major flaws in the 7-line C program, even ignoring character set issues. (main returns int, argv[1] can be null, and strncpy doesn't always null-terminate the target). If you're going to compare languages, you should find someone who knows each of them well.
- deleted 11y ago[deleted]
- deleted 11y ago[deleted]
- BinaryIdiot 11y agoI'm not sure what the takeaway is from this blog entry. Is it that Python 3 can do substrings easier than the other languages therefore we should use Python 3? That was what I thought it was, anyway. Seems silly to pick a language based off this single, silly criteria otherwise why not JavaScript or probably other languages that can make the code even smaller? console.log(mystring.substring(0, 12)); So it just seems arbitrary and weak in my opinion.
- steeleduncan 11y agoThe entire scenario seems to have been constructed to highlight the runtime panic caused by out of bounds slices in Go. Either that or the well-known and well-discussed lack of generics.
- edofic 11y agoA mandatory smart-ass Haskell response import System.Environment (getArgs) main = do [str] <- getArgs putStrLn $ take 12 str
- nicolast 11y agoNow with more operators! import System.Environment (getArgs) main = putStrLn =<< take 12 . head <$> getArgs ;-)
- coldtea 11y agoWell, for smart-ass (and I know you meant it as a joke) is not very impressive. Don't do anything more than the others, and the syntax is not so great either.
- Veedrac 11y agoOn the contrary, his is the only one that crashes when more arguments than expected are passed. Hooray progress!
- joeyh 11y agoThe actual smart-ass haskell response is simply "take 12". The spec didn't specify this needed to be a impure shell command, so a pure function is obviously better.
- BossHogg 11y agoArticle content aside, the slide out side menu that covers the scroll bar is incredibly annoying. Is that Blogger? Whatever it is needs to stop. Now.
- Ianvdl 11y agoThe author awards some arbitrary points to C even though his implementation of the solution is broken. His similarly poor Go implementation receives zero of these arbitrary points. Why does this deserve the attention of everyone here? The author did not compare languages, he compared his aptitude with these languages, and considered broken implementations to somehow be comparable. A more meaningful comparison would be to implement simple, efficient, working solutions to these problems and comparing them. This, as it stands, does not lead to any useful discussion.
- darkstalker 11y agoRust version: fn main() { if let Some(arg) = std::env::args().nth(1) { println!("{}", arg.chars().take(12).collect::<String>()); // chars() iteraters over codepoints } }
- Veedrac 11y agoIdiomatic Rust would probably avoid allocations, which means something more like fn main() { if let Some(arg) = std::env::args().nth(1) { println!("{}", { match arg.char_indices().nth(12) { Some((idx, _)) => &arg[..idx], None => &*arg } }); } } With the `unicode-segmentation` crate[1], you can just swap `char_indices()` with `grapheme_indices(true)`. [1] https://crates.io/crates/unicode-segmentation https://crates.io/crates/unicode-segmentation
- deleted 11y ago[deleted]