Timeline for C# Dev - I've tried Lisps, but I don't get it
Current License: CC BY-SA 2.5
26 events
when toggle format | what | by | license | comment | |
---|---|---|---|---|---|
Mar 23, 2013 at 15:37 | comment | added | gtrak | In the simple example of reimplementing 'if', you already impose something on the client interface of that code. Thus, there is additional abstraction that can't take place. If this were the way 'if' was implemented, I would call it through a macro so my code wouldn't have to thunk everything manually. The hassle avoided grows at scale, but macros also provide efficiency benefits at the expense of clarity. IMO, the clarity of reading expanded code is overblown, or people wouldn't use C over assembly. Macros let you to make those tradeoffs yourself without being at the mercy of MS. | |
Aug 7, 2012 at 17:58 | comment | added | defhlt | @MasonWheeler So to recap our little discussion I would say in lisps "code is (structured like) data" but "not all data is code". | |
Aug 7, 2012 at 17:39 | comment | added | Mason Wheeler | @ArtemIce: Then that's not treating data and code as equivalent. It's treating data and code as completely distinct things that play by different rules, which is the correct way to do it. | |
Aug 7, 2012 at 17:34 | comment | added | defhlt |
@MasonWheeler I mean if SQL had S-expresion syntax it will treat this data as code (= username user-name) and turn it in something like (filter (fn [username] ~where-arg) usernames) and then (filter (fn [username] (= username "whatever user entered as his username")) users) . So what ever user will put as username it will be treated as string, not S-expression.
|
|
Aug 7, 2012 at 17:09 | comment | added | defhlt |
@MasonWheeler I don't see how lisp's 'code as data' can make code injection easier. Actually, I believe it makes injection much more difficult. Consider this: "SELECT * FROM users WHERE username = " + user_name + ";" is dangerous because we evaluating user input. But in lisps it could look like (select users-table (where (= :username user-name))) . Lisp will run this code (= :username user-name) for each username in db checking equality to user-name string value. user-name does not evaluate.
|
|
Jun 18, 2012 at 18:17 | comment | added | Mason Wheeler | "Code as data" is a very bad idea, and I'm glad that more languages haven't picked it up. Just look at SQL. Every time you see in the news about some site getting hacked and divulging millions of users' private information due to a SQL injection attack, it's because some programmer failed to properly separate code from data. | |
Apr 11, 2011 at 8:17 | comment | added | Vatine | @Ingo: Werllll... It's bordering on a chore to override the 978 symbols that form the core of Common Lisp (not difficult, per se, just requires that you create a package that doesn't import anything from package COMMON-LISP). So, most of teh time, anything outside the language core is not entirely obvious. But, as things can mutate state without clearly indicating so, it's not really an extra burden. | |
Apr 10, 2011 at 9:42 | comment | added | Ingo | @Vatine - I see, but doesn't that mean that a lisp programmer can't see the semantics of some piece of code without looking at the implementation? | |
Apr 10, 2011 at 9:24 | comment | added | Vatine | @ingo Haskell is "saved" by lazy evaluation. Try implementing that in "Haskell with eager evaluation" (not taht such a beast exist, but it'll give you an insight into where the problem lies). | |
Apr 10, 2011 at 1:44 | comment | added | Ingo | I wonder what is going on in a language where such a simple thing like if can't be defined as a function, as it is stated here? In Haskell, for example, this would be just myif True t e = t; myif False t e = e; | |
Feb 22, 2011 at 17:39 | comment | added | semperos | A look at Incanter or Enlive or Conjure or Moustache should all be pretty clear examples of how macros stand apart. | |
Feb 21, 2011 at 18:17 | comment | added | WReach | Also see the SO question What can you do with Lisp macros that you can't do with first-class functions? | |
Feb 21, 2011 at 18:13 | comment | added | SK-logic | @Jonathan Mitchem, LINQ syntax is a nice example of what can be done with macros, but had to be implemented in a language core instead, as the language does not support any decent metaprogramming. | |
Feb 21, 2011 at 17:31 | comment | added | Jonathan Mitchem | @mblinn @Rörd: I'm having some trouble getting a Clojure environment set up with an IDE, but I'm going to give that a chance. It seems I really need to get my head around this macro thing and see why it's so important. The idea of maintaining lexical context with a macro makes a bit of sense to me, versus with a function. It's not something I could explain to the average C# dev though, unfortunately. Let me play for a few days. Thanks for the feedback. | |
Feb 21, 2011 at 3:59 | comment | added | mblinn | @Rörd right, but a macro lets you do so without passing in either quoted code or a closure... | |
Feb 21, 2011 at 3:56 | comment | added | mblinn | @Jonathan Mitchem It's hard to identify a case were should can use a macro. That's actually not a question you ask when you're programming in a lisp. What happens is you identify a pattern, and then you modify the language to fit that pattern. That may, or may not, require using a macro. I think one of the reason that the my-if example is so popular is because lisp lets you define language constructs that are as powerful as the ones that come with the language, and "if" is a construct that any programmer understands. | |
Feb 21, 2011 at 0:49 | comment | added | Rörd | Basically with a function you have a choice to accept either quoted code, which you can walk but it's missing its lexical context because you're walking and executing it in the lexical context of your function. Or you can accept closures, which keep their lexical context but you can only call, not walk them or add something to their lexical context. To do both you need a macro, which can walk and wrap the code before its expansion will be placed into the lexical context of the macro call. | |
Feb 21, 2011 at 0:33 | comment | added | Rörd |
I agree that macros are worthwhile, but it isn't true that a my-if requires them, it can be written as a higher-order function (see a CL example below). You only really need macros if you want to walk the code or place it in a new lexical context. (defun my-if (test then &optional else) (cond (test (funcall then)) ('otherwise (funcall else))))
|
|
Feb 20, 2011 at 18:20 | comment | added | Jonathan Mitchem | Hm. "class Name { }" is pretty compact. As far as refactoring, there's inheritance to handle many cases, and extension methods (akin to defmethod, as far as I can tell) to handle the rest. I'm really not trying to be difficult here; I'm just searching for some brain-bending example that once I get my head around it, I think "oh, that's why this is a big deal, wow!" | |
Feb 20, 2011 at 18:15 | comment | added | Gabe |
If you've ever had to implement INotifyPropertyChanged or DependencyProperty , you would know that you can't refactor out all boilerplate. Macros would be a great way to simplify these in C#.
|
|
Feb 20, 2011 at 17:36 | comment | added | Alex Baranosky | Macros enable you to refactor out code that must be change pre-compile. For example, class definitions that have the same structure. | |
Feb 20, 2011 at 17:09 | comment | added | Jonathan Mitchem | It's going to take me a bit of time to grok that example. For me, "saving boilerplate code" usually invokes the term "refactoring", which is part of why the explanations haven't convinced me. I have a solution that works in every instance I've applied it. I think then the question is how do you identify cases where you can use a macro? | |
Feb 20, 2011 at 16:51 | comment | added | mblinn | In that case, the macro saves a bunch of boilerplate code. The macros that I write tend to be of that variety. Like I mentioned, most of Clojure is implemented in Clojure. It's hard to imagine the implications of that. It means you can implement almost any language feature you need when you need to. You've probably heard these arguments before, and probably better stated. I known none of them convinced me. What convinced me was the first time I ran into a situation where I realized I could write one macro, and ended up saving hundreds of lines of code... | |
Feb 20, 2011 at 16:44 | comment | added | mblinn | Here's an example from another Stack Overflow question. stackoverflow.com/questions/5035086/… | |
Feb 20, 2011 at 16:40 | comment | added | Jonathan Mitchem | Without touching any code, I ran through the scenario of implementing an "if" without macros in my head, both in Clojure and C#. It effectively (or literally) can't be done. I admit that's neat. But I'm missing the connection of how that's useful to me. What can I do with macros (besides write "if") that I can't do with clever functional or OO-design? "How could this help me" isn't a valid criteria for evaluating a language, but it is for evaluating whether I'll use it. (I really want a Lisp to be worth switching to, but it hasn't hit the point of becoming a viable alternative.) | |
Feb 20, 2011 at 16:20 | history | answered | mblinn | CC BY-SA 2.5 |