use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
詳しくは検索FAQを参照
高度な検索: 投稿者や、subredditで……
906 人のユーザーが現在閲覧しています
/r/programming is a reddit for discussion and news about computer programming
Guidelines
Please try to keep submissions on topic and of high quality.
Just because it has a computer in it doesn't make it programming.
Memes and image macros are not acceptable forms of content.
If there is no code in your link, it probably doesn't belong here.
App demos should include code and/or architecture discussion.
Please follow proper reddiquette.
Info
Do you have a question? Check out /r/learnprogramming, /r/cscareerquestions, or stackoverflow.
Do you have something funny to share with fellow programmers? Please take it to /r/ProgrammerHumor/.
For posting job listings, please visit /r/forhire or /r/jobbit.
Check out our faq. It could use some updating.
If you're an all-star hacker (or even just beginning), why not join the discussion at /r/redditdev and steal our reddit code!
Related reddits
/r/technology
/r/learnprogramming
/r/askprogramming
/r/coding
/r/compsci
/r/dailyprogrammer
/r/netsec
/r/webdev
/r/web_design
/r/gamedev
/r/cscareerquestions
/r/reverseengineering
/r/startups
/r/techsupport
Specific languages
Why doesn't Python have switch/case? (pydanny.com)
nathan2779 が 1日前 投稿
[–]lambdaq 6ポイント7ポイント8ポイント 1日前 (4子コメント)
IMHO Ruby's case...when syntax is a work of art. You can have regex and range match ups.
case...when
[–]Jazztoken 5ポイント6ポイント7ポイント 1日前 (1子コメント)
With a name like lambda q, I'd think you'd see that as child's play. Give me functional pattern matching or give me death!
[–]iconoclaus 0ポイント1ポイント2ポイント 7時間前 (0子コメント)
see Elixir if you like Rubyesque syntax but need a functional approach.
[–]Freeky 3ポイント4ポイント5ポイント 1日前 (0子コメント)
For those unfamiliar:
case foo when "foo", "bar" when SomeClass when 0..42 when /somepattern/ end
Boils down to syntax sugar for:
if "foo" === foo || "bar" === foo elsif SomeClass === foo elsif 0..42 === foo elsif /somepattern/ === foo end
So it's just calling the === method on each matching object and letting it pattern match as appropriate - equality check, class ancestory check, range inclusion check, regexp match, etc.
===
[–]Godd2 0ポイント1ポイント2ポイント 1日前* (0子コメント)
It will also call procs for you, passing in the object of interest. If the proc returns something truthy, it's considered a match. Just be careful of side effects!
n = 3 case n when :even?.to_proc puts "It's an even number!" when :odd?.to_proc puts "It was a dumb odd number..." end It was a dumb odd number...
To be clear, it still calls #=== on the proc, it's just that the case equality method calls the proc.
#===
a = proc {3} a === 4 => 3 a === "hello" => 3
[–]FearlessFreep 5ポイント6ポイント7ポイント 1日前* (0子コメント)
I spent years doing Smalltalk, which also doesn't have a switch/case and I think I'd been programming in Python for over a year before I even realized it didn't have a switch/case.
The pseudo-Smalltalk perspective (which tends to be a pure-OO perspective) is partially that methods should be small and switch/case statements tend not to be small structures. But beyond that, usually a switch/case is seen as a bad design "If I'm over here and testing that object to make a bunch of decisions, then the decision probably really doesn't belong here but should be someplace else....either in that object or some in between Visitor, etc.." This tends to work well in Smalltalk for a number of reasons
I now program mostly Python I still more or less follow this philosophy. When I break it I usually just use a dictionary where the keys are the possible test conditions and the values are some sort of executable (lambda or function call)
[–]skulgnome 17ポイント18ポイント19ポイント 1日前 (2子コメント)
Because it doesn't have static typing, and so wouldn't stand to gain from compiling it to a table lookup or binary search.
[–]combinatorylogic 4ポイント5ポイント6ポイント 1日前 (1子コメント)
It's not an issue if the case variants are literals.
[–]dangerbird2 4ポイント5ポイント6ポイント 1日前 (0子コメント)
There are basically zero control structures in Python requiring a literal input. Differentiating compile-time literals and runtime objects doesn't make sense in python, as all values are objects, and all objects are treated as first-class citizens.
[–]bigfig 7ポイント8ポイント9ポイント 1日前 (4子コメント)
So it's more difficult, and what doesn't kill you makes you stronger.
[–]combinatorylogic 27ポイント28ポイント29ポイント 1日前 (1子コメント)
Exactly. The next topic: "How coding in Brainfuck made me a better programmer".
[–]Yojihito 11ポイント12ポイント13ポイント 1日前 (0子コメント)
Ook. Ook.
[–]Randosity42 -1ポイント0ポイント1ポイント 6時間前 (1子コメント)
What's more difficult about it? A dictionary of functions works just as well, and has the benefit of being an object.
[–]bigfig 0ポイント1ポイント2ポイント 5時間前 (0子コメント)
I dunno, I was summarizing the opinion piece as I understood it. Otherwise I have no opinion.
[–]remember_the_aylmao 9ポイント10ポイント11ポイント 1日前* (12子コメント)
class Switch(object): def __call__(self, value): if not self.verbose: if self.switched_value == value: if self.fall_through: self.default = True self.cont = True else: self.default = False self.cont = False return True elif self.cont: return True else: return False else: return bool(value) def __init__(self, value, verbose = False, fall_through = True): self.switched_value = value self.cont = False self.default = True self.verbose = verbose self.fall_through = fall_through def fall(self): self.default = True self.cont = True def stop(self): self.default = False self.cont = False def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): pass
Here's how you use it:
from switch_case import Switch as case with case(n) as when: if when(0): print 'You typed zero' when.stop() if when(1): pass if when(9): print 'n is a perfect square' when.stop() if when(2): pass if when(4): pass if when(6): pass if when(8): print 'n is an even number' when.stop() if when(2): pass if when(3): pass if when(5): pass if when(7): print 'n is a prime number' when.stop() if when.default: print 'Only single-digit numbers are allowed'
[–]tdz9 15ポイント16ポイント17ポイント 1日前 (2子コメント)
WUT My eyes!!! My eyesssss!!!
[–]remember_the_aylmao 0ポイント1ポイント2ポイント 17時間前 (0子コメント)
It could be worse. I could have modified the AST like they do in macropy
[–]bms676 0ポイント1ポイント2ポイント 1日前 (0子コメント)
MY EYES!!
[–]vattenpuss 1ポイント2ポイント3ポイント 1日前 (0子コメント)
Smalltalk also has no switch statement. But it's easily added, as in this suggested solution from c2:
Object subclass: #Case instVars: 'criterion satisfied response' Case>>for: anObject ^self new criterion: anObject Object>>switch ^Case for: self Case>>case: oneArgTestBlock then: execBlock "The oneArgTestBlock must return a Boolean value when passed the criterion of the receiver." satisfied ifFalse: [(oneArgTestBlock value: criterion) ifTrue: [response := execBlock value. satisfied := true]]. Case>>default: execBlock satisfied ifFalse: [response := execBlock value]. ^response
And then we can use it, as in your example:
n switch case: [:x | x = 0] then: ['You typed zero' print]; case: [:x | x = 9] then: ['n is a perfect square' print]; case: [:x | x = 8] then: ['n is an even number' print]; case: [:x | x = 7] then: ['n is a prime number' print]; default: ['Only single-digit numbers are allowed' print].
[–]amertune 2ポイント3ポイント4ポイント 1日前 (4子コメント)
More common would be something like this:
from collections import defaultdict cases = defaultdict(lambda: 'Only single-digit numbers are allowed') cases.update({ 0: lambda: print('You typed zero'), 1: lambda: None, 2: lambda: None, 3: lambda: None, 4: lambda: None, 5: lambda: None, 6: lambda: None, 7: lambda: print('n is a prime number'), 8: lambda: print('n is an even number'), 9: lambda: print('n is a perfect square') })
Which would be used like this (REPL example)
> cases[9]() n is a perfect square > cases[6]() > cases['what is this?']() Only single-digit numbers are allowed
[–]brombaer3000 1ポイント2ポイント3ポイント 1日前 (2子コメント)
Does this structure with defaultdicts have any advantages over the structure used in the first example of the blog post (i.e. using a normal dict and the dict.get(index, default) method or are they equivalent?
dict.get(index, default)
[–]amertune 1ポイント2ポイント3ポイント 1日前 (1子コメント)
They're equivalent. I'd favor dict.get(index, default) if the dict was only used in one place, but if I had multiple dict.get calls with the same default I'd prefer using a defaultdict.
[–]brombaer3000 1ポイント2ポイント3ポイント 1日前 (0子コメント)
Ah, I see what you mean now: The dictionary definition itself is prettier using normal dicts, but with defaultdicts you can safely use the more readable bracket syntax for access (dict[index]()), which is nice if you have to write it more than once.
dict[index]()
[–]remember_the_aylmao 0ポイント1ポイント2ポイント 16時間前 (0子コメント)
Lamdba/dict syntax that people frequently suggest for python misses the ability to use fall through or complex expressions like case(x - 2 > 3).
[–]DrinkingAndFighting 2ポイント3ポイント4ポイント 1日前 (1子コメント)
Seems performant...
I suppose you want to have your cake and eat it too? It's python man. Everything is a PyObject. Embrace the chaos.
[–]knome 0ポイント1ポイント2ポイント 1日前 (0子コメント)
Similar to the one I devised.
https://github.com/knome/Hacks/blob/master/python/switch/test.py
[–]notconstructive 1ポイント2ポイント3ポイント 21時間前 (0子コメント)
It's easy to write dict based dispatchers in Python to do the same thing.
[–]rabidcow 9ポイント10ポイント11ポイント 1日前 (8子コメント)
You can do this easily enough with a sequence of if... elif... elif... else.
That's disgusting.
There have been some proposals for switch statement syntax, but there is no consensus (yet) on whether and how to do range tests.
Oh, well that makes sense, then. I mean, it's pretty obvious to me that you shouldn't, but I understand the allure.
[–]Deto 8ポイント9ポイント10ポイント 1日前* (7子コメント)
Why's it disgusting? I think that If-"else-if"-else feels more natural to anyone who isn't already used to switch-case from another language. Also, the need for "break" statements to prevent fall-through violates the principle of least surprise (or at least, I've never heard of anyone expecting this behavior before being told that's what will happen). Of course, you could get rid of this for a Python version, but then the only difference between switch/case is using different words than if/elif/else. Sure in other languages, it's more efficient because you can directly jump to the case without evaluating every condition, but it looks like this might not be as feasible in Python.
[–]rabidcow 3ポイント4ポイント5ポイント 1日前 (5子コメント)
Sure in other languages, it's more efficient because you can directly jump to the case without evaluating every condition, but it looks like this might not be as feasible in Python.
I don't know why it wouldn't be feasible; I'd make switch essentially syntactic sugar for a dictionary lookup. But it's not a matter of efficiency, it's that you can consider a single branch without having to check all the others to make sure they don't overlap. Worse case, you might have a duplicate, which is much easier to see and obviously incorrect.
If-ladders also make you repeat the discriminant over and over, which is just pointless noise. Until there's that one branch that checks a different variables and you didn't notice...
[–]Eirenarch 1ポイント2ポイント3ポイント 1日前 (4子コメント)
I think that switch is extremely ugly construct and it is not justified in any language. I do use it because it is already there in C style languages but if I had to put together a language switch certainly wouldn't make it in (better have something else). I understand why it was invented in the ancient days just to have a jump table but not today.
[–]rabidcow 3ポイント4ポイント5ポイント 1日前 (3子コメント)
What do you see as ugly about it? Do you disagree with my point about big sequences of if-else?
[–]el_tacomonkey 2ポイント3ポイント4ポイント 1日前 (1子コメント)
I'll jump in. They're both hideous in some sense because they're the same thing. The problem isn't with the syntax (although it would be easy to say the syntax is ugly too), the problem is that you have to hold more things in your head for a longer period of time to read either a switch ... case or if ... elif ... elif than most other expressions.
def the_answer = 42
does not require you to hold much in your head. It's obvious, you can make the association easily. If .. else isn't bad if the inside expression isn't complicated or is self-documentingly named. You only have to "push one thing on the stack" in your mind to get it. To me, that's a beautiful line of code. Switch statements (and their cousin the if else sequences make you keep a bunch of things in mind at the same time while you're reading through the code. Not only do you have to have all that in mind, you have to remember what execution paths didn't happen. That's harder. Not impossible, not by any means, just harder. And your brain only has the time and bandwidth to deal with so many efforts in one day it's "hideous" to "waste" one of them working through complicated control flows.
I think they're hideous because I would have preferred to spend that "mental compute cycle" on the problem of WHY I'm reading this code.
[–]rabidcow 0ポイント1ポイント2ポイント 23時間前 (0子コメント)
the problem is that you have to hold more things in your head for a longer period of time to read either a switch ... case or if ... elif ... elif than most other expressions.
Yes! This is exactly my problem with if-ladders, but I'd argue that a properly designed switch feature would not have this problem. Think something like what C has, but with fall-through either forbidden or explicit.
[–]Eirenarch 0ポイント1ポイント2ポイント 1日前 (0子コメント)
I think the switch syntax is extremely heavy in C-style languages (2 keywords, braces, columns, breaks required, etc.) In fact I cannot think of a construct that is heavier on syntax than the switch statement. In addition the functionality of switch statement is trivially replicated with if/else.
[–]Serializedrequests 0ポイント1ポイント2ポイント 1日前 (0子コメント)
You could do it like Ruby, and not require the break statement. If you combine several cases, you separate them with commas. Voila, shorter and a little more readable than if-elsif-else and way more readable than C.
[–]SilasX 1ポイント2ポイント3ポイント 21時間前* (0子コメント)
Because python prefers "there should be one way of doing it"
elif x ==
+=1
++
Per the Zen of Python
There should be one-- and preferably only one --obvious way to do it.
[–]MpVpRb 0ポイント1ポイント2ポイント 1日前 (7子コメント)
I can't imagine writing code without a switch statement
I use finite state machines a lot, and switch seems to work well for them
Also, communication protocols with commands represented in an enumeration..switch seems tailor made to handle these
I have no idea why it was omitted from Python
Maybe the author valued philosophical purity more than usefulness
[–]dangerbird2 3ポイント4ポイント5ポイント 1日前 (0子コメント)
That's pretty much the whole point of Python. It's a language controlled by a Benevolent Dictator for Life with language features designed to ensure readable code with consistent idioms across the entire ecosystem.
[–]Workaphobia 2ポイント3ポイント4ポイント 1日前 (5子コメント)
Maybe the same reason there's no do loop: Because it's not so much more expressive compared to existing alternatives that it warrants making the language more complex.
do
Yes there are cases like FSMs that map well onto switches (although I don't know why a FSM needs case fall-through as the norm, rather than the exception). But using a dictionary, or methods, is not such a bad idea either. If you can't tolerate the overhead of a method lookup, you're in the wrong language anyway.
[–]MpVpRb 0ポイント1ポイント2ポイント 1日前 (0子コメント)
not so much more expressive
I consider it more readable, and I consider readability to be very important
[–]MsEtheldreda 0ポイント1ポイント2ポイント 1日前 (3子コメント)
That sounds like the same reason the Go developers use for omitting important features that people want.
[–]Workaphobia 1ポイント2ポイント3ポイント 1日前 (2子コメント)
If you put in everything that people want, you end up with C++.
Well, I guess it doesn't have garbage collection (yet), but you know what I mean.
[–]MsEtheldreda -4ポイント-3ポイント-2ポイント 1日前 (1子コメント)
That isn't even a reasonable comparison. Switch is literally one of the most basic features ever that basically every sane language supports.
[–]Workaphobia 2ポイント3ポイント4ポイント 1日前 (0子コメント)
Then why not the do loop? Why not goto? Why not C-style for loops? Why not multi-level break/continue? (Admittedly, that last one isn't supported in most C-style languages, but it has been requested.)
The fact that other languages have something is not a reason in and of itself for Python to add it. Particularly when Python already has idioms for dealing with the issue in a reasonable way.
[–]Pangloss_ex_machina -1ポイント0ポイント1ポイント 1日前 (15子コメント)
The only thing that I miss in Python is the lack of a ternary operator.
[–]combinatorylogic 16ポイント17ポイント18ポイント 1日前 (14子コメント)
There is a ternary operator in Python - a conditional expression.
[–]Pangloss_ex_machina 8ポイント9ポイント10ポイント 1日前 (7子コメント)
You're right.
Many years using ? and : in other languages and I forgot about this.
[–]masklinn 5ポイント6ポイント7ポイント 1日前 (6子コメント)
tbf the conditional expression is relatively recent (Python 2.5), before that you had to make do with condition and if_true else if_false
condition and if_true else if_false
[–]LightShadow 3ポイント4ポイント5ポイント 1日前 (3子コメント)
relatively
"Python 2.5 was released on September 19th 2006."
[–]masklinn 1ポイント2ポイント3ポイント 1日前 (2子コメント)
Keep in mind there's a non-empty population of developers for whom the cutoff is less "when was the feature originally released in" and more "when was a version containing that feature released in RHEL/Debian Stable" or even worse "when was the last version not supporting that feature dropped from support".
I had to rewrite part of a script for a RHEL 5 server. The old version used the "x if test() else y" form, and I had to revert to the older "test() and x or y" style. It's less readable, but it works the same.
[–]masklinn 0ポイント1ポイント2ポイント 1日前 (0子コメント)
It's less readable, but it works the same.
Not exactly, it fails in one situation (which IME is relatively rare, but it happens): if x is falsy, you'll always get y.
x
y
[–]definitely-lying 1ポイント2ポイント3ポイント 1日前 (1子コメント)
I've also seen {True: val1, False: val2}[condition], but yeah it was these various ternary hacks that made them add it, since many of the ternary hacks don't work in the general case and/or aren't lazy.
{True: val1, False: val2}[condition]
[–]ohias 2ポイント3ポイント4ポイント 18時間前* (0子コメント)
Actually a thing like that can be simpler than a ternary operator if all you need is just an already computed value:
>>> ("false","true")[2 > 1] 'true'
Or it's love for K/Q/J speaking in me
[–]_theowen_ 5ポイント6ポイント7ポイント 1日前 (1子コメント)
A if C else B
[–]rabidcow 2ポイント3ポイント4ポイント 1日前 (3子コメント)
Although the syntax is like a little slice of Perl.
[–]skulgnome 0ポイント1ポイント2ポイント 1日前 (1子コメント)
It's not rarely that I see ($a && $b) || $c. Easy to tell which languages inherit from Lisp and which do from C.
($a && $b) || $c
[–]PM_ME_YOUR_PAULDRONS 0ポイント1ポイント2ポイント 21時間前 (0子コメント)
I've not encountered that pattern before. Doesn't it break if $b is false (or coerced into something falsely in languages which do that)? If $b is falsely and $c is true you'll get $c instead even if $a is true won't you?
[–]HookahComputer 0ポイント1ポイント2ポイント 1日前 (0子コメント)
A unless B else C
[+]combinatorylogic スコアが基準値未満のコメント-10ポイント-9ポイント-8ポイント 1日前 (100子コメント)
I'm avoiding using Python exactly because of the lack of switch and goto. It breaks all of my preferred code generation practices. FSMs are absolutely essential and fundamental. It was not a good idea to strip a language from the most adequate ways of implementing FSMs.
switch
goto
[–]joonazan 19ポイント20ポイント21ポイント 1日前 (40子コメント)
It is easy to program a much cleaner Finite State Machine by making every state a function that returns the next state. This works in C too and does not fill the Stack. So don't blame Python for ignoring a very common and convenient way to make a FSM.
Code for a textbook finite state machine:
state = start for symbol in string: state = state(symbol)
[+]combinatorylogic スコアが基準値未満のコメント-8ポイント-7ポイント-6ポイント 1日前 (39子コメント)
It's a very slow way and it's not friendly to the code generation (due to an unnecessary state separation). Try parsing a binary protocol this way, for example.
[–]Ericis 10ポイント11ポイント12ポイント 1日前* (28子コメント)
Chances are whatever you generate in Python, even if it had goto and switch, it'd be "slow". It's an interpreted script language. So what do you generate in. C?
[–]combinatorylogic -4ポイント-3ポイント-2ポイント 1日前 (27子コメント)
The problem is, I have to generate multiple languages from the same source. And I have to aim for the maximum possible performance for each language, including even JavaScript (e.g., generating an Atom semantic highlighting mode out of a declarative language specification).
So, yes, of course I'm generating a fast machine code directly, but I also have to be able to generate Python, JavaScript, e-lisp and many more.
[–]Ericis 6ポイント7ポイント8ポイント 1日前* (26子コメント)
And I have to aim for the maximum possible performance for each language, including even JavaScript (e.g., generating an Atom semantic highlighting mode out of a declarative language specification).
Good, so maximum performance for Python is using what Python has. Problem solved. If someone needs faster, then can use your output for a faster language. Problem solved again.
Also mainstream JS engines are about 20 times faster than Python due to advanced JIT, so the "even" is not warranted.
[–]combinatorylogic -3ポイント-2ポイント-1ポイント 1日前 (25子コメント)
If someone needs faster, then can use your output for a faster language.
Firstly, these limitations on performance are there for no reason at all. Just some stupid religion of the language designers.
Secondly, in a captive audience scenario you simply cannot choose another language.
[–]Ericis 3ポイント4ポイント5ポイント 1日前 (21子コメント)
The language designers also support C extensions for all the edge cases that scripting is not suitable for.
Scripting is intended for very specific use cases written by humans. Claiming it's "some stupid religion" because they don't cater to your edge case which is only harming the primary target of the language is infantile.
You said you avoid Python for your FSM, now we have captive audience where you can't avoid Python. Which is it, and who's holding them captive and for what reason?
[+]combinatorylogic スコアが基準値未満のコメント-9ポイント-8ポイント-7ポイント 1日前 (20子コメント)
Code generation should never be considered an edge case, it must always be the default scenario for any language. If language designers do so, they're incompetent and their language is a pile of crap, period.
You said you avoid Python for your FSM
I said I want to avoid it and most often succeed in doing so, but there are exceptionally annoying cases where I cannot.
Integration with Scons is one such example.
[–]Ericis 5ポイント6ポイント7ポイント 1日前 (19子コメント)
Code generation should never be considered an edge case, it must always be the default scenario for any language.
The only languages where this is the default scenario are IR stages in parsers, opcodes in runtimes, and machine code. If you care so deeply, use the right tools for the right job.
[–]kirbyfan64sos 2ポイント3ポイント4ポイント 1日前 (2子コメント)
Try telling that to the millions of companies that use Python every day. You can't say the limitations on performance are stupid until you've implemented a programming language.
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (1子コメント)
Millions of companies are using Cobol or PHP.
You can't say the limitations on performance are stupid until you've implemented a programming language.
I implemented dozens of languages.
[–]kirbyfan64sos -1ポイント0ポイント1ポイント 1日前 (0子コメント)
Ok, let me try this again:
Try telling that to the millions of companies that use Python every day and enjoy it.
Scripting languages as dynamic as Python is?
[–]joonazan 10ポイント11ポイント12ポイント 1日前 (9子コメント)
Very slow is not true. You might get a small performance boost matching an opcode using a switch vs. using a table of function pointers, but I was talking about FSMs.
In FSMs, using function pointers is faster, because your state does not need to be translated to a jump location. It is just stupid to save the state as an enum if you can save it as jump location.
If your states share data, make them methods or closures or use global variables.
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (8子コメント)
because your state does not need to be translated to a jump location
How is it "translated" to a jump location if it is a direct goto straight away, with all the benefits of a stable branch prediction?
make them methods or closures or use global variables.
Adding another level of indirection, making the whole thing even slower.
[–]jms_nh 1ポイント2ポイント3ポイント 1日前 (0子コメント)
with all the benefits of a stable branch prediction?
You have a point there.
[–]joonazan 0ポイント1ポイント2ポイント 1日前 (6子コメント)
I assume you have a state variable that has an integer value. Now don't try to tell me you can jump to that directly.
Statically dispatched methods are not noticeable slower, they compile to a function that gets one extra pointer. On the other hand, the benefit is huge: suddenly you can have multiple FSMs co-operating on some complicated task.
If you aren't ready to pay that price, use globals. Because you can't run another instance of the FSM anyways before the last one has finished, you lose nothing.
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前 (5子コメント)
Now don't try to tell me you can jump to that directly.
With goto, one state jump to another directly. No need for a state variable at all.
With switch, it's one level of indirection (if implemented with a jump table).
And, having a single dispatch point with a fixed jump table is most often beneficial for the branch prediction and cache locality.
If you aren't ready to pay that price, use globals.
You're suggesting lifting all the local variables accessible to the FSM states to globals? A bit harsh.
[–]joonazan 0ポイント1ポイント2ポイント 1日前* (4子コメント)
That's what programming in C is like. Use a struct or namespace to avoid polluting the global namespace.
If you're willing to do that, I don't see how polluting the global namespace is harsh. I can only imagine the errors caused by effectively moving to unstructured programming.
EDIT: And yes, I have used goto. I used it in an outline tracing algorithm. I almost never use it tho, because Golang can break or continue a loop of your choice.
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (0子コメント)
I can only imagine the errors caused by effectively moving to unstructured programming.
Wow, that's scary!!! Now you have to throw away your computer and run. The CPU inside is an awful, evil thing with all those branch instructions inside.
Seriously, why would you care if your generated code is not structured? And writing FSMs manually instead of generating them out of the higher level DSLs is just stupid.
[–]combinatorylogic -4ポイント-3ポイント-2ポイント 1日前 (2子コメント)
Use a struct or namespace to avoid polluting the global namespace.
And all this crap because some dimwit decided that switch contradicts the Pythonic religion?
[–]joonazan -1ポイント0ポイント1ポイント 1日前 (1子コメント)
I would definitely use function pointers in C instead of a switch.
In Python, I'd use a dict and think it's much faster to code than a switch.
[–]Ericis 14ポイント15ポイント16ポイント 1日前 (9子コメント)
Switch and goto are handy for generating FSM, but hardly "essential" or "fundamental".
Instead of switch and map, you can, say, use a dict to map to a lambda and call it.
[–]combinatorylogic -3ポイント-2ポイント-1ポイント 1日前 (8子コメント)
They're fundamental in a sense that any sane way of generating a code for these abstractions would unavoidably go via an IR with labels, gotos and switches. So, in order to translate such an IR into some other base, like a bunch of mutually recursive functions, for example, you have to do additional transforms, even a decompilation in the worst cases.
[–]Ericis 3ポイント4ポイント5ポイント 1日前 (7子コメント)
"Labels" and "gotos" and "switches" doesn't sound very IR to me. Looks like you need to adjust the separation lines in your abstractions. A mapping of a value to a piece of code can be represented by a dict of lambdas just as seamlessly. It can even be faster if your states are many.
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前* (6子コメント)
"Labels" and "gotos" and "switches" doesn't sound very IR to me.
Of course, the IR is made of basic blocks with direct, indirect and switch terminal nodes. Labels and gotos are a bit higher level than that.
It can even be faster if your states are many.
And why should I care? Why could not Python interpreter decide the best way to implement a switch in this particular context?
Not to mention it's a bad, leaky abstraction. If it's naturally a switch, it must be a switch, not a "dictionary" with "lambdas" (how did these abstractions, totally unrelated to the problem domain, leak into our nice, dense, readable code?!?).
[–]Ericis 0ポイント1ポイント2ポイント 1日前* (5子コメント)
You're getting increasingly wanting, aren't you? Next comment you'll be asking why the Python interpreter doesn't directly implement your FSM generator for you, and put a cherry on top.
A switch is just syntax sugar over a bunch of ifs in most languages out there. Since you generate code, ranting about syntax sugar which is irrelevant to your project is bizarre.
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前* (4子コメント)
Next comment you'll be asking why the Python interpreter doesn't directly implement your FSM generator for you, and put a cherry on top.
No, I can do it on my own. I only want the underlying language to provide the reasonable, common set of control flow abstractions that are present in all the other languages belonging to the same semantic class.
A switch is just syntax sugar over a bunch of ifs in most languages out there
No. Most languages would use smart heuristics to choose the appropriate implementation of a switch.
Since you generate code, ranting about syntax sugar which is irrelevant to your project is bizarre.
It's not bizarre, it's totally reasonable. Each abstraction must be lowered on an appropriate level. I do not possess enough information on higher levels of code generation chain to choose how exactly a switch should be lowered, it's down to the host language implementation to use all the local function control flow information to decide the correct implementation.
In other words, a knowledge of how to optimise a simple control flow structure should not leak above the core language level.
[–]Ericis 0ポイント1ポイント2ポイント 1日前 (3子コメント)
I'm calling bullshit on this unless you have sources. The most I've heard is a compiler reordering cases to do a binary search, when applicable. Something which, again, is very trivial in a code generator to implement, as is your case.
And don't pick some obscure language I've never heard of.
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前 (2子コメント)
I'm calling bullshit on this unless you have sources.
Take a look at various LLVM backends. They all default to different selection thresholds and use different ways of implementing jump tables.
[–]Ericis 0ポイント1ポイント2ポイント 1日前 (1子コメント)
"Take a look at various X" is not a source.
[–]Paddy3118 4ポイント5ポイント6ポイント 1日前 (26子コメント)
Your clearly not new to programming, but seem to need a language with this particular language construct rather than the alternatives offered. Fine, Python can't please everyone.
[+]combinatorylogic スコアが基準値未満のコメント-10ポイント-9ポイント-8ポイント 1日前 (25子コメント)
The alternatives do not work, or work so poorly that it raises questions about the language designers sanity.
I'd be delighted to ignore Python altogether, it's a very poorly designed and generally unpleasant language anyway. The problem is the same as with Java - huge ecosystem with a captive audience.
In order to serve this audience one have to deal with Python (or Java, or whatever else). And those who designed those languages should have known better that the code is not always written manually.
Each and every language must provide decent support for code generation. If language designers neglected this important mode of use, the language is broken by design.
And, btw., I believe that goto haters should not be allowed to program at all. It's an extremely powerful red flag allowing to filter out incompetence efficiently.
[–]rgeyz 11ポイント12ポイント13ポイント 1日前 (1子コメント)
Another red flag is being an ass.
Plenty of people use Python for everyday tasks that are very far removed from what you seem to be willing to use it for. Dismissing it as broken for the lack of what you call "decent support for code generation" is silly (not to mention that people have been doing code generation with Python for years).
[+]combinatorylogic スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント 1日前 (0子コメント)
You know, people use Cobol every day. Would it be rude to call Cobol broken by design? Or PHP? Or cmd?
And, no, Python is not suited for code generation. People are using it in a very silly way, nothing interesting.
[–]hawker1368 2ポイント3ポイント4ポイント 1日前 (12子コメント)
And, btw., I believe that goto haters should not be allowed to program at all.
Interestingly, I believe the exact opposite. Hopefully we will never have to work together :)
[+]combinatorylogic スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント 1日前* (11子コメント)
I believe the exact opposite
The difference between our beliefs is tremendous. I can formally prove that I'm right. And you, well, simply believe, for no other reason but some stupid religion.
[–]hawker1368 1ポイント2ポイント3ポイント 1日前 (10子コメント)
You can formally prove that your approach is more optimized. We agree on that.
But in my book, this is always readability first, and then only optimizations. Never the opposite. And goto are not readable.
[–]MsEtheldreda 2ポイント3ポイント4ポイント 1日前 (0子コメント)
Goto can be perfectly readable providing you have reasonable guidelines the same as with every single other programming language feature.
You can formally prove that your approach is more optimized.
No. I can formally prove that my approach is semantically sound, more robust and more verifiable.
this is always readability first, and then only optimizations
And I'm talking about the readability, if you did not notice.
And goto are not readable.
Did I ever say I want to write a code containing goto manually? Did I say I want to read such a code?
[–]hawker1368 2ポイント3ポイント4ポイント 1日前 (7子コメント)
You can prove mathematically that your code is more readable for humans than another one ? Well, this is a first for me, so color me curious. Can you please name which technique allows you to do that ?
So basically, you don't like Python because you want to generate Python code hyper-optimized that nobody will ever read again ? You do realize Python is designed for the very opposite, right ?
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (6子コメント)
You can prove mathematically that your code is more readable for humans than another one ?
I can infer how close a language is to a problem domain language, and what is the number of unrelated concepts in it.
Can you please name which technique allows you to do that ?
By measuring semantic distance between a practical language and an abstract, clean language of a problem domain specification.
you want to generate Python code hyper-optimized
I care more about simplicity of code generation rather than optimisations (the latter would be nice, but simplicity is more important). Clumsy control flow harms simplicity.
You do realize Python is designed for the very opposite, right ?
And this is what I hate in Python. Any language which is not designed with code generation in mind is a shitty language, because ANY language MUST be a code generation target, always.
Exactly for the reasons of readability and maintainability. DSLs are always more readable than the general purpose languages, and DSLs imply code generation.
[–]hawker1368 5ポイント6ポイント7ポイント 1日前* (5子コメント)
If I understand you correctly, you can mathematically figure out the best programming language for a specific set of problems ? It makes sense.
Now, I think the reality of the job makes this approach unpractical at best. Programmers usually have a lot of various problems to solve, even just in the course of a week. Also I know no programmers that have time to learn every existing languages. So professionally speaking, I think it makes more sense for a programmer to learn two or three generalist languages and be good at it, than to try to learn many of them, and suck at all of them.
Fact is, Python is a generalist language that allows humans to write programs very quickly, in a very readable fashion. So it can make sense to use it
Also, your approach doesn't match what I would call "readability". For instance, it doesn't take into account whether the syntax is explicit to English-speaking humans or not (see for example the operator "not in" ; if "a" not in ["b", "c", "d"]:). To take a exaggerated example, I have a feeling it could indicate BrainFuck as the best choice for some problems because of its very reduced set of concepts.
if "a" not in ["b", "c", "d"]:
Any language which is not designed with code generation in mind is a shitty language, because ANY language MUST be a code generation target, always.
For me, what you say is like saying "every tool must be able to screw screws". Except not everybody need a screwdriver. Some need a hammer most of the time for their job.
Clearly, I agree that Python is not designed with code generation in mind at all. This is unfortunate that you have to use it for that, but it simply wasn't on its specifications when designed.
Now, before saying it's a shitty language, I think you should take into account that 99% of the programmers don't have to generate Python code. At best, sometimes, they use it to generate code in other languages, but not the opposite.
In the end, Python is a very "human" programming language. I can understand that not everybody like it. But saying it's a shitty language because it can't be generated easily just tells me you simply didn't understand its purpose.
[–]kdelok 1ポイント2ポイント3ポイント 1日前 (1子コメント)
Appropriate language choice and features depend on the task at hand. The tasks you seem to have been describing generally represent lower level tasks, often those you might associate with computer science or computational science.
However, there are plenty of programming tasks where the important factors are not speed, memory usage or avoiding stack overflow. We have an implementation of our code in Fortran and a parallel version in Python. The Python version allows for much faster prototyping of new functionality by relatively novice programmers. This is extremely important, as many of the people we work with are scientists first and programmers second. The Fortran is computationally quicker, but our limiting factor is the ability of our coders and users to answer the questions we have. In many cases the Python is just better for this, regardless of slower run times.
[–]combinatorylogic -3ポイント-2ポイント-1ポイント 1日前 (0子コメント)
The tasks you seem to have been describing generally represent lower level tasks
Uhm, no, I'm talking about being able to seamlessly integrate a code in Python with a code generated from some very high level domain-specific languages.
The Python version allows for much faster prototyping of new functionality by relatively novice programmers.
And how exactly a presence of a switch statement would have harmed this ability?
[–]Paddy3118 0ポイント1ポイント2ポイント 1日前 (7子コメント)
I see you are incensed enough to complain. Are you moved enough to write your own language?
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前 (6子コメント)
Are you moved enough to write your own language?
How would it help if I have to use Python (and, even worse, Scons specifically)? I implemented numerous languages - after all, this is what I'm talking about here, using arbitrary Domain Specific Languages on top of any possible host, including Python.
[–]Paddy3118 0ポイント1ポイント2ポイント 1日前 (5子コメント)
Hmm, if you have a tool that generates C-style switch statements and possibly makes use of either extra break statements in a case block, or maybe not terminating a case block with a break statement then automatic translation to nested/concatenated if/elsif statements is non-trivial It would still be possible however, just difficult.
Is there any way to get the logic expressed without such switch statements?
[–]combinatorylogic 1ポイント2ポイント3ポイント 1日前 (4子コメント)
It would still be possible however, just difficult.
That's exactly what I'm talking about. Far too many DSL semantics involve having an IR with a classic control flow, including switch dispatch and, often, labels and gotos.
Reversing from this IR level to the peculiar Python control flow adds more complexity (and more opportunities to screw up).
They're all more complex than an ad hoc, trivial lowering.
[–]Paddy3118 0ポイント1ポイント2ポイント 1日前 (3子コメント)
Unfortunately, it seems that you will remain disappointed with Python as your use-case doesn't fit the wide range of uses that Python is geared for. Goto's and labels are considered very low-level and if added to a language would lead to their misuse as people tried to hand code with them rather than the auto-generation of code you speak of. That is anathema to the Python community who prefer constructs that aid readability and maintainability by people. So, no goto's no labels, no assignment within expressions, no pointer arithmatic, no ... it ain't gonna happen.
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (2子コメント)
as your use-case doesn't fit the wide range of uses that Python is geared for
My point is that my use case should be universal. If a language is not suitable for code generation, it's a shitty language for any possible use case - because code generation adds value to any language, on any level of abstraction, for any possible domain.
Goto's and labels are considered very low-level and if added to a language would lead to their misuse
That's why I would have been ok with an 'unsafe' keyword annotating such a code and making it less attractive to do it manually.
[–]Paddy3118 0ポイント1ポイント2ポイント 1日前 (1子コメント)
I'm afraid your view of reality is disjoint from my own and I suspect most readers here, giving us no basis for reply. Bye :-)
[–]hawker1368 3ポイント4ポイント5ポイント 1日前 (11子コメント)
Regarding switch, the article pretty much says what I think: you don't really need them. Also, Python is a object-oriented language. So if sometimes you feel like you need a switch with 100+ as suggested in the article, my feeling is that you're doing things the wrong way.
It's even more true with goto: In C, the only reasonable use for goto that I know is to handle errors. In Python, you're supposed to use exceptions.
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前 (10子コメント)
you don't really need them
Which is wrong. You need them if you want to do the dispatch locally, without recursive calls. And you really, really want to do this if you're implementing a huge, long running FSM and do not want to worry about a stack overflow.
my feeling is that you're doing things the wrong way.
I do not care how big the code is. I'm not writing it, I'm not reading it. It's a throwaway code that I'm generating from higher level languages. Pity it must interact with something in the Python ecosystem, and therefore it have to be written in Python too.
All those broken languages designers are always oblivious of the fact that the code is not necessarily written by hand and can be generated.
the only reasonable use for goto that I know is to handle errors
There are dozens of other reasonable uses for goto. Including implementing FSMs, efficient VM interpreters, and multiple code generation target languages.
In Python, you're supposed to use exceptions.
That's why I do not want to use Python for anything. I hate languages that are trying to enforce their religion on me.
[–]Workaphobia 6ポイント7ポイント8ポイント 1日前 (1子コメント)
You need them if you want to do the dispatch locally, without recursive calls.
Dunno about locally, but you don't need recursive calls if you make each handler a method that updates an state variable.
Ooookkayyy... So your other options are to 1) generate if/elif instead of a switch statement, 2) generate methods instead of a switch statement, 3) generate dict lookups instead of a switch statement, 4) generate freaking CPython byte codes instead of a switch statement. You're not working in Python as a source language so I don't see why you care which approach you generate so long as you aren't growing the stack without bound.
Including implementing FSMs, efficient VM interpreters, and multiple code generation target languages.
Implementing FSMs can be done with if/elif or the other ways I mentioned. Efficient VM interpreters? If you're so concerned about efficiency that you need it to branch with goto/switch instead of something else, then you probably don't want to be working with the Python interpreter anyway. You do know that executing each individual Python opcode requires many times the amount of jumping that a C-level switch would do.
You must love C++. The fact is that writing a code generator for a language requires that you actually use features of the target language. That not all languages are the same is not the fault of Python.
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (0子コメント)
updates an state variable.
Of course. A state variable that is used in a switch inside a loop. Oops - no switch?
1) generate if/elif instead of a switch statement
That's exactly what I do for lowering the small switches, and function dictionaries for the larger ones. And it's an additional translation step which would not be needed for a more expressive target language.
generate freaking CPython byte codes instead of a switch statement
There is no switch byte code.
then you probably don't want to be working with the Python interpreter anyway
Of course I do not want to touch Python with a ten feet pole. But sometimes I have to (e.g., when the generated code must be used from inside a Scons script, and I want to avoid producing any host binaries in this environment).
That not all languages are the same is not the fault of Python.
I am not complaining about the lack of goto and switch in Haskell. They're not there for a very good reason. Although, for Python, there is no reason at all, and that's why I'm angry.
[–]jmtd 2ポイント3ポイント4ポイント 1日前 (5子コメント)
Pity it must interact with something in the Python ecosystem, and therefore it have to be written in Python too.
I'd challenge this assertion. Can you embed python into a C program, target your FSM generation to C, and use the Python/C interface to talk to the Python thing?
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (4子コメント)
Can you embed python into a C program, target your FSM generation to C, and use the Python/C interface to talk to the Python thing?
I can, but it's a lot more hassle than if the host language (Python) could support more expressive control flow.
It is especially painful if the resulting code must be available as a Python library and must be used by the Python scripts. In my case, the most common scenario is generated parser and generated visitors chain (both heavily dependant on switch or goto presence in the target language).
I think, all the languages must be code-generation friendly. Use the 'unsafe' keyword or whatever else equally intimidating to scare the coders off using the "dangerous" features, but leave them for those who know what they're doing.
[–]RedditPrisoner420 1ポイント2ポイント3ポイント 1日前 (3子コメント)
You must be talking about a pretty trivial program if rewriting it is easier than compiling with Cython... Python has pretty extensive support for using ctypes.
[–]combinatorylogic -2ポイント-1ポイント0ポイント 1日前 (2子コメント)
I'm talking about a generated high level code which have an FSM fabric interleaved with a Python code chunks.
[–]RedditPrisoner420 1ポイント2ポイント3ポイント 1日前 (1子コメント)
I might just be misunderstanding, but I'm still not sure why you couldn't hook the properly-generated C code into Python using ctypes, unless there's differences in behavior between the generated Python and C programs.
Because this generated code should call back to Python a lot, which may require a lot of scaffolding in both ways.
E.g., think of a parser with semantic actions implemented in Python for each terminal.
[–]dangerbird2 0ポイント1ポイント2ポイント 1日前 (1子コメント)
You obviously should not be using python. Hell its this module is literally prints out the language's "religious" doctrine
this
[–]combinatorylogic -1ポイント0ポイント1ポイント 1日前 (0子コメント)
You obviously should not be using python.
I know. If I could only avoid it, but, unfortunately, it's not always possible.
[–]antihexe 0ポイント1ポイント2ポイント 1日前 (8子コメント)
Sometimes I can't tell if people are trolling or not.
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (7子コメント)
Do you consider, say, Donald Knuth a troll?
On the other hand, Dijkstra was a well known troll, and his brilliant trolling consequences are still visible, in form of all this religious goto hate.
[–]antihexe 0ポイント1ポイント2ポイント 1日前 (6子コメント)
On the internet nobody knows you're Donald Knuth?
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (5子コメント)
Donald Knuth is a well known goto advocate. Is he trolling?
[–]Ericis 3ポイント4ポイント5ポイント 1日前* (2子コメント)
"Most goto-s shouldn’t be there in the first place! What we really want is to conceive of our program in such a way that we rarely even think about go to statements, because the real need for them hardly ever arises."
[–]combinatorylogic -3ポイント-2ポイント-1ポイント 1日前 (1子コメント)
Goto is the essence of control flow. What you want is pure dataflow programming. It's fine. I prefer the dataflow languages too. But in order to implement such languages and embed them into the other, lesser languages you'd still need goto.
[–]Ericis 2ポイント3ポイント4ポイント 1日前 (0子コメント)
I was quoting Donald Knuth.
[–]antihexe 1ポイント2ポイント3ポイント 1日前 (1子コメント)
Programming style, like writing style, is somewhat of an art and cannot be codified by inflexible rules, although discussions about style often seem to center exclusively around such rules.
Many opinions on programming style are just that: opinions. They may be strongly argued and strongly felt, they may be backed up by solid-seeming evidence and arguments, but the opposing opinions may be just as strongly felt, supported, and argued. It's usually futile to get dragged into "style wars," because on certain issues, opponents can never seem to agree, or agree to disagree, or stop arguing.
Style is one thing, it's subjective and all that. Semantics, on the other hand, is a very formal discipline, a subject for formal proofs, not the subjective opinions.
To use goto or not is a pointless question of a style. To allow goto or not in a language is a question of semantics and it's totally open to a proper scientific scrutiny.
[–]SnowdensOfYesteryear 0ポイント1ポイント2ポイント 1日前 (0子コメント)
Why do you need goto for FSMs? Usually a standard loop is enough.
[+]Ruudjah スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント 1日前 (13子コメント)
I hate switch with a passion. It's never needed and in Java and C# an excuse not to do proper polymorphic dispatch.
[–]tsimionescu 14ポイント15ポイント16ポイント 1日前 (0子コメント)
Oh yes, create a hierarchy of classes inheriting from each other instead of using one statement. In absolutely all cases, that is the proper design - anything else is just laziness. Think of how easy it is to tell what gets called: unlike the switch where you need to look for the code block with the given case Value label, you simply have to walk the class hierarchy!
case Value
[–]combinatorylogic 1ポイント2ポイント3ポイント 1日前 (9子コメント)
It's never needed
Never coded an FSM? Never implemented a fast bytecode interpreter? Never implemented a fast binary protocol parsing?
proper polymorphic dispatch
Only if "proper" means "slow and potentially overflowing" in your language.
[–]joonazan 2ポイント3ポイント4ポイント 1日前 (8子コメント)
So you want switch because you want a jump table? Why not code a jump table?
Switch is very rarely needed. And when it is, it is for performance. You can use a hash map instead, it is just slower. So Python definitely does not need a switch statement, because no one codes high-performance things in Python.
[–]ohias 0ポイント1ポイント2ポイント 1日前 (2子コメント)
And how do you implement fallthrough in a hash map exactly?
[–]joonazan 0ポイント1ポイント2ポイント 20時間前 (1子コメント)
Elif chains are good if you need that. If you use fallthrough, your switch is linear anyway.
[–]ohias 0ポイント1ポイント2ポイント 18時間前* (0子コメント)
except it would be a) slower, b) more verbose, c) harder to understand, d) error prone and harder to refactor.
Especially if you have code like:
case Foo: do smth assign smth if (check smth) break; do smth more case Bar: if (check smth more) break; case Baz: ...
This code will be exceptionally convoluted with just IF's
I mean it would be a replacement for a switch for sure, but in no way a good one.
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (4子コメント)
So you want switch because you want a jump table?
I want a switch. I do not want (in many cases) to care about the most efficient way to implement it. Compilers use exceptionally complex heuristics to choose between an if tree and a jump table when lowering a switch - see the x86 LLVM backend for example.
And when it is, it is for performance.
It is for abstraction over various high performance implementations.
because no one codes high-performance things in Python.
But when you're confined to Python you want to get the maximum possible performance within this constraints.
And, again, an abstraction: switch, goto and labels are natural semantic blocks occurring in many intermediate languages lowering paths. If your host language does not support them, you have to do a lot of additional code transforms on top, meaning more potential for errors and worse performance for no good reason.
[–]Workaphobia 0ポイント1ポイント2ポイント 1日前 (0子コメント)
If you're trying to avoid method lookups in Python, you shouldn't be using Python. The very language itself requires dictionary hashing and dynamic attribute lookup for almost every operation. If you think you're keeping things close down to the wire by making your FSM cases part of the intraprocedural control flow instead of separate methods, you should look more closely into the implementation in CPython.
As for your argument about code generation that you've used here and elsewhere in this thread, you gotta stop acting as if switches are the only way or even the most natural way to translate a FSM description into imperative code. There's no reason you can't produce a few method ASTs in place of a big control structure.
[–]joonazan -4ポイント-3ポイント-2ポイント 1日前 (2子コメント)
Python is good for solving some (not super resource intensive) problem in under five minutes. Are you even aware that it is interpreted?
If you really want a switch, because you like the syntax, elif is just fine.
elif
[–]combinatorylogic 0ポイント1ポイント2ポイント 1日前 (1子コメント)
Are you even aware that it is interpreted?
Are you even aware that even interpreted code can (and often should) be optimised?
If you really want a switch
I want a switch with dozens to hundreds of entries. So far, my only option is a dictionary, and it sucks badly.
Does the dictionary solution suck because it's syntactically uglier, or because it incurs hashing penalties? If it's the latter, why don't you switch to a different data structure that doesn't hash? For example, a list, so long as your keys are state integers that are more or less sequential.
For code prettiness, you can annotate the list entries with comments so the reader of the generated code can easily see their index; or else you can use a dictionary and then convert that dictionary into a list programmatically outside of the main loop.
[–]ohias 0ポイント1ポイント2ポイント 1日前 (0子コメント)
Someone who never wrote any parsers/SM/VMs detected, I guess?
[–]Workaphobia -1ポイント0ポイント1ポイント 1日前 (0子コメント)
It's also has a theoretical wart: It's the only structured programming language feature that causes the program's control flow graph to have arbitrary fan-out. This means that programs can have an arbitrarily large tree-width, making them more difficult to run some kinds of static analysis on.
[+]lucidguppy スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント 1日前 (2子コメント)
You should really be using fewer switch cases anyway (maybe a few in the factory functions - to make polymorphic types)
[–]MsEtheldreda 3ポイント4ポイント5ポイント 1日前 (0子コメント)
That sounds like Java-tier "all problems can be solved by another level of indirection" logic to me.
A variant of this is the official answer to every deficiency of Python.
[–]anacrolix -1ポイント0ポイント1ポイント 19時間前 (3子コメント)
Use a dict ffs. Don't mangle the language.
[–]ohias 0ポイント1ポイント2ポイント 18時間前 (2子コメント)
how would this look with a dict?
[–]Randosity42 0ポイント1ポイント2ポイント 5時間前 (1子コメント)
A dictionary of functions. A complex switch statement should be broken into functions anyway.
[–]ohias 0ポイント1ポイント2ポイント 4時間前 (0子コメント)
So could you then show me how my example would look like as a dictionary of functions? It's not very complex, only 9 lines.
[+]Ishmael_Vegeta スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント 1日前 (0子コメント)
because it is a cult language.
[+]RyanTheLionHearMeRor スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント 1日前 (0子コメント)
I never use case statements in any language and always use if else. More readable IMO
π Rendered by PID 7490 on app-05 at 2015-09-05 21:47:41.895472+00:00 running f67e6f2 country code: JP.
[–]lambdaq 6ポイント7ポイント8ポイント (4子コメント)
[–]Jazztoken 5ポイント6ポイント7ポイント (1子コメント)
[–]iconoclaus 0ポイント1ポイント2ポイント (0子コメント)
[–]Freeky 3ポイント4ポイント5ポイント (0子コメント)
[–]Godd2 0ポイント1ポイント2ポイント (0子コメント)
[–]FearlessFreep 5ポイント6ポイント7ポイント (0子コメント)
[–]skulgnome 17ポイント18ポイント19ポイント (2子コメント)
[–]combinatorylogic 4ポイント5ポイント6ポイント (1子コメント)
[–]dangerbird2 4ポイント5ポイント6ポイント (0子コメント)
[–]bigfig 7ポイント8ポイント9ポイント (4子コメント)
[–]combinatorylogic 27ポイント28ポイント29ポイント (1子コメント)
[–]Yojihito 11ポイント12ポイント13ポイント (0子コメント)
[–]Randosity42 -1ポイント0ポイント1ポイント (1子コメント)
[–]bigfig 0ポイント1ポイント2ポイント (0子コメント)
[–]remember_the_aylmao 9ポイント10ポイント11ポイント (12子コメント)
[–]tdz9 15ポイント16ポイント17ポイント (2子コメント)
[–]remember_the_aylmao 0ポイント1ポイント2ポイント (0子コメント)
[–]bms676 0ポイント1ポイント2ポイント (0子コメント)
[–]vattenpuss 1ポイント2ポイント3ポイント (0子コメント)
[–]amertune 2ポイント3ポイント4ポイント (4子コメント)
[–]brombaer3000 1ポイント2ポイント3ポイント (2子コメント)
[–]amertune 1ポイント2ポイント3ポイント (1子コメント)
[–]brombaer3000 1ポイント2ポイント3ポイント (0子コメント)
[–]remember_the_aylmao 0ポイント1ポイント2ポイント (0子コメント)
[–]DrinkingAndFighting 2ポイント3ポイント4ポイント (1子コメント)
[–]remember_the_aylmao 0ポイント1ポイント2ポイント (0子コメント)
[–]knome 0ポイント1ポイント2ポイント (0子コメント)
[–]notconstructive 1ポイント2ポイント3ポイント (0子コメント)
[–]rabidcow 9ポイント10ポイント11ポイント (8子コメント)
[–]Deto 8ポイント9ポイント10ポイント (7子コメント)
[–]rabidcow 3ポイント4ポイント5ポイント (5子コメント)
[–]Eirenarch 1ポイント2ポイント3ポイント (4子コメント)
[–]rabidcow 3ポイント4ポイント5ポイント (3子コメント)
[–]el_tacomonkey 2ポイント3ポイント4ポイント (1子コメント)
[–]rabidcow 0ポイント1ポイント2ポイント (0子コメント)
[–]Eirenarch 0ポイント1ポイント2ポイント (0子コメント)
[–]Serializedrequests 0ポイント1ポイント2ポイント (0子コメント)
[–]SilasX 1ポイント2ポイント3ポイント (0子コメント)
[–]MpVpRb 0ポイント1ポイント2ポイント (7子コメント)
[–]dangerbird2 3ポイント4ポイント5ポイント (0子コメント)
[–]Workaphobia 2ポイント3ポイント4ポイント (5子コメント)
[–]MpVpRb 0ポイント1ポイント2ポイント (0子コメント)
[–]MsEtheldreda 0ポイント1ポイント2ポイント (3子コメント)
[–]Workaphobia 1ポイント2ポイント3ポイント (2子コメント)
[–]MsEtheldreda -4ポイント-3ポイント-2ポイント (1子コメント)
[–]Workaphobia 2ポイント3ポイント4ポイント (0子コメント)
[–]Pangloss_ex_machina -1ポイント0ポイント1ポイント (15子コメント)
[–]combinatorylogic 16ポイント17ポイント18ポイント (14子コメント)
[–]Pangloss_ex_machina 8ポイント9ポイント10ポイント (7子コメント)
[–]masklinn 5ポイント6ポイント7ポイント (6子コメント)
[–]LightShadow 3ポイント4ポイント5ポイント (3子コメント)
[–]masklinn 1ポイント2ポイント3ポイント (2子コメント)
[–]amertune 1ポイント2ポイント3ポイント (1子コメント)
[–]masklinn 0ポイント1ポイント2ポイント (0子コメント)
[–]definitely-lying 1ポイント2ポイント3ポイント (1子コメント)
[–]ohias 2ポイント3ポイント4ポイント (0子コメント)
[–]_theowen_ 5ポイント6ポイント7ポイント (1子コメント)
[–]rabidcow 2ポイント3ポイント4ポイント (3子コメント)
[–]skulgnome 0ポイント1ポイント2ポイント (1子コメント)
[–]PM_ME_YOUR_PAULDRONS 0ポイント1ポイント2ポイント (0子コメント)
[–]HookahComputer 0ポイント1ポイント2ポイント (0子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-10ポイント-9ポイント-8ポイント (100子コメント)
[–]joonazan 19ポイント20ポイント21ポイント (40子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-8ポイント-7ポイント-6ポイント (39子コメント)
[–]Ericis 10ポイント11ポイント12ポイント (28子コメント)
[–]combinatorylogic -4ポイント-3ポイント-2ポイント (27子コメント)
[–]Ericis 6ポイント7ポイント8ポイント (26子コメント)
[–]combinatorylogic -3ポイント-2ポイント-1ポイント (25子コメント)
[–]Ericis 3ポイント4ポイント5ポイント (21子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-9ポイント-8ポイント-7ポイント (20子コメント)
[–]Ericis 5ポイント6ポイント7ポイント (19子コメント)
[–]kirbyfan64sos 2ポイント3ポイント4ポイント (2子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (1子コメント)
[–]kirbyfan64sos -1ポイント0ポイント1ポイント (0子コメント)
[–]joonazan 10ポイント11ポイント12ポイント (9子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (8子コメント)
[–]jms_nh 1ポイント2ポイント3ポイント (0子コメント)
[–]joonazan 0ポイント1ポイント2ポイント (6子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (5子コメント)
[–]joonazan 0ポイント1ポイント2ポイント (4子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (0子コメント)
[–]combinatorylogic -4ポイント-3ポイント-2ポイント (2子コメント)
[–]joonazan -1ポイント0ポイント1ポイント (1子コメント)
[–]Ericis 14ポイント15ポイント16ポイント (9子コメント)
[–]combinatorylogic -3ポイント-2ポイント-1ポイント (8子コメント)
[–]Ericis 3ポイント4ポイント5ポイント (7子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (6子コメント)
[–]Ericis 0ポイント1ポイント2ポイント (5子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (4子コメント)
[–]Ericis 0ポイント1ポイント2ポイント (3子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (2子コメント)
[–]Ericis 0ポイント1ポイント2ポイント (1子コメント)
[–]Paddy3118 4ポイント5ポイント6ポイント (26子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-10ポイント-9ポイント-8ポイント (25子コメント)
[–]rgeyz 11ポイント12ポイント13ポイント (1子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント (0子コメント)
[–]hawker1368 2ポイント3ポイント4ポイント (12子コメント)
[+]combinatorylogic スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント (11子コメント)
[–]hawker1368 1ポイント2ポイント3ポイント (10子コメント)
[–]MsEtheldreda 2ポイント3ポイント4ポイント (0子コメント)
[–]combinatorylogic -3ポイント-2ポイント-1ポイント (8子コメント)
[–]hawker1368 2ポイント3ポイント4ポイント (7子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (6子コメント)
[–]hawker1368 5ポイント6ポイント7ポイント (5子コメント)
[–]kdelok 1ポイント2ポイント3ポイント (1子コメント)
[–]combinatorylogic -3ポイント-2ポイント-1ポイント (0子コメント)
[–]Paddy3118 0ポイント1ポイント2ポイント (7子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (6子コメント)
[–]Paddy3118 0ポイント1ポイント2ポイント (5子コメント)
[–]combinatorylogic 1ポイント2ポイント3ポイント (4子コメント)
[–]Paddy3118 0ポイント1ポイント2ポイント (3子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (2子コメント)
[–]Paddy3118 0ポイント1ポイント2ポイント (1子コメント)
[–]hawker1368 3ポイント4ポイント5ポイント (11子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (10子コメント)
[–]Workaphobia 6ポイント7ポイント8ポイント (1子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (0子コメント)
[–]jmtd 2ポイント3ポイント4ポイント (5子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (4子コメント)
[–]RedditPrisoner420 1ポイント2ポイント3ポイント (3子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (2子コメント)
[–]RedditPrisoner420 1ポイント2ポイント3ポイント (1子コメント)
[–]combinatorylogic -2ポイント-1ポイント0ポイント (0子コメント)
[–]dangerbird2 0ポイント1ポイント2ポイント (1子コメント)
[–]combinatorylogic -1ポイント0ポイント1ポイント (0子コメント)
[–]antihexe 0ポイント1ポイント2ポイント (8子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (7子コメント)
[–]antihexe 0ポイント1ポイント2ポイント (6子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (5子コメント)
[–]Ericis 3ポイント4ポイント5ポイント (2子コメント)
[–]combinatorylogic -3ポイント-2ポイント-1ポイント (1子コメント)
[–]Ericis 2ポイント3ポイント4ポイント (0子コメント)
[–]antihexe 1ポイント2ポイント3ポイント (1子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (0子コメント)
[–]SnowdensOfYesteryear 0ポイント1ポイント2ポイント (0子コメント)
[+]Ruudjah スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント (13子コメント)
[–]tsimionescu 14ポイント15ポイント16ポイント (0子コメント)
[–]combinatorylogic 1ポイント2ポイント3ポイント (9子コメント)
[–]joonazan 2ポイント3ポイント4ポイント (8子コメント)
[–]ohias 0ポイント1ポイント2ポイント (2子コメント)
[–]joonazan 0ポイント1ポイント2ポイント (1子コメント)
[–]ohias 0ポイント1ポイント2ポイント (0子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (4子コメント)
[–]Workaphobia 0ポイント1ポイント2ポイント (0子コメント)
[–]joonazan -4ポイント-3ポイント-2ポイント (2子コメント)
[–]combinatorylogic 0ポイント1ポイント2ポイント (1子コメント)
[–]Workaphobia 0ポイント1ポイント2ポイント (0子コメント)
[–]ohias 0ポイント1ポイント2ポイント (0子コメント)
[–]Workaphobia -1ポイント0ポイント1ポイント (0子コメント)
[+]lucidguppy スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント (2子コメント)
[–]MsEtheldreda 3ポイント4ポイント5ポイント (0子コメント)
[–]HookahComputer 0ポイント1ポイント2ポイント (0子コメント)
[–]anacrolix -1ポイント0ポイント1ポイント (3子コメント)
[–]ohias 0ポイント1ポイント2ポイント (2子コメント)
[–]Randosity42 0ポイント1ポイント2ポイント (1子コメント)
[–]ohias 0ポイント1ポイント2ポイント (0子コメント)
[+]Ishmael_Vegeta スコアが基準値未満のコメント-7ポイント-6ポイント-5ポイント (0子コメント)
[+]RyanTheLionHearMeRor スコアが基準値未満のコメント-6ポイント-5ポイント-4ポイント (0子コメント)