Re: [Lift] Reasoning Behind Box
Daniel, Thanks for asking the question and I hope the discussion will go better than the last time we had an in depth discussion on the topic. I'm going to respond in a Prologue, History, Reactions, Code Examples and Conclusion. *Prologue* I'm not a classically trained CS guy. I've never taken an FP-related CS course in my life. I've only done any real FP-related coding since November 2006. I've only taken 3 CS courses in my entire life (360 assembler [almost got thrown out because the teacher hated the fact that I always found bugs in her homework assignments during the class in which she handed out the assignments], data structures and algorithms [got accused of cheating on mid-term because my sorting algorithm ran 10x faster than the next fastest... turns out I randomized the incoming data {avoids O(n^2) issue in QuickSort} and created faux-pointers and sorted those rather than the structures {this was in Pascal}], and a database theory class [almost got thrown out because the comments in my code were considered "unprofessional"... rescued my grade by writing a hand SQL parser rather than using Flex/Bison]). The reason I say this is that I'm not going to discuss ADTs, mathematical properties, or anything else. I'm not qualified or capable of having that kind of discussion. I'm also lazy and pragmatic. If a library works for me, I use it. If a library requires a lot of working-around, I ask for fixes and if I don't get them, I write my own. I did this with the NextStep Text object... it didn't have what I needed for Mesa, the Next guys weren't happy about giving what I needed... I wrote my own... then the Next guys rolled a lot of my concepts into the NS Text object. The same thing happened with the NextStep font chooser... in fact, Mesa's font chooser was the first piece of open source software I wrote... but I digress. *History* Back when I was the only Lift committer (okay, maybe SteveJ had commit rights back then... I don't remember) and I was working on the first Lift-based app, I was experiencing a nasty issue. This was summer of 2007. This was circa Scala 2.4 and before Either was in the language. One of the common patterns I kept running across was iterating through a series of pieces of user-input (both from the UI and from the REST interfaces) and having to return a not-answer (None) and the reason for the inability to complete the operation. It was about the same time, moved away from pattern matching against Options in favor of using Options in for comprehensions. The first thing I tried was to use Options in conjunction with exceptions (yeah, I was still lost in Java-think) such that in the case of a None for a particular operation (loading an item from the database, etc.), I'd throw an exception, the caller would catch the exception and present the right thing to the user/caller. It was ugly. I posted to the Scala mailing list and, well... there were not a lot of good suggestions other than use Either (e.g., write my own Either library). The problem with Either is that it was not usable in for comprehensions and pattern matching was becoming increasingly deprecated. One of our advisors (http://www.lukehohmann.com/ ) was particularly keen on keeping a low McCabe complexity number for code (see http://en.wikipedia.org/wiki/Cyclomatic_complexity ). For comprehensions offered a very low complexity where pattern matching explodes complexity. So, I finally bit the bullet and wrote my own set of classes that offered the kind of functionality that I was cobbling together with Option. I originally called the class Can (a short name for something that contains or does container a unit of something... a can of soup, a can of beans.) I patterned Can after Option (btw, Option is one of the worst names in the Scala libraries... explaining what an Option is to a Java or Ruby guy was one of my biggest stumbling blocks... Maybe would have been a much better name, but I digress.) Can became a better Option. In addition to having Full/Empty (Some/None), it also had Failure... a subclass that could contain information as to why the Can did not contain anything. From an object hierarchy standpoint, Can and Option are identical at the first children: Full == Some. EmptyCan == None. The other problems I saw with Option were: - The get method was too easy for Java (and Ruby) developers to "get wrong". Get is *FREAKING DANGEROUS*. It's an exception waiting to happen. It should not be used except in the most extreme situation. But with a nice, tasty, comforting, access-worthy name like "get", it just begs to be invoked. Something like 30% of our production-time defects resulted from mis-using Option.get. This needed to be changed... so something that says "danger" like "open_!" Oh, yeah, the "!" says "hmmm... why is that ! there? Should I be using this method?" - orElse orElse orElse... who named this method. In terms of method naming the "Else"
Re: [Lift] Reasoning Behind Box
On 26 February 2010 08:09, Naftoli Gugenheim wrote: > Either -- but it's more verbose. > I'm not so sure David will want to rewrite the entire lift anyway... > Right now, I only would like to listen to Daniel, OK? Heiko Company: weiglewilczek.com Blog: heikoseeberger.name Follow me: twitter.com/hseeberger OSGi on Scala: scalamodules.org Lift, the simply functional web framework: liftweb.net -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Reasoning Behind Box
Either -- but it's more verbose. I'm not so sure David will want to rewrite the entire lift anyway... - Heiko Seeberger wrote: Daniel, I would like to look at this question from a solution oriented perspective: Certainly you already noticed the third Box subtype Failure and are aware of its usage. I agree with you, that Option vs Box is confusing for Lift (and nowadays Goat Rodeo) adopters. As Scala and Lift are still very young adoption is vital and hence I would like to know, what you suggest: How could we only use Option *and* get something like Failure? Any ideas? Heiko On 26 February 2010 05:40, Daniel Spiewak wrote: > I'm sure this has been discussed before, but I'm curious as to the > rationale for the Box ADT. I'm most distressed by the fact that it > seems to be masquerading as a drop-in Option replacement, and yet the > mathematical properties of the ADT are widely divergent. What's more, > the API is very, very different, leading to a great deal of confusion > whenever I'm working with code which touches both ADTs (as I often > do). Things like `or` vs `orElse`, `open_!` vs `get` and so on are > very confusing. The implicit conversion Box[A] => Option[A] doesn't > help either, since it means I can easily forget and use Option methods > on Box values, accidentally triggering a conversion. > > The whole `or` vs `orElse` thing is particularly annoying since I > spend a fair amount of time wading through research which discusses > the `orElse` function in its abstract monadic sense. Given the > standard nature of the name (dating back long before Scala), I'm > surprised that Box went with something else. > > I'm sure there are good reasons for all of this, I would just like to > know what they are. :-) > > Daniel > > -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to lift...@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscr...@googlegroups.com > . > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en. > > -- Heiko Seeberger Company: weiglewilczek.com Blog: heikoseeberger.name Follow me: twitter.com/hseeberger OSGi on Scala: scalamodules.org Lift, the simply functional web framework: liftweb.net -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Reasoning Behind Box
Daniel, I would like to look at this question from a solution oriented perspective: Certainly you already noticed the third Box subtype Failure and are aware of its usage. I agree with you, that Option vs Box is confusing for Lift (and nowadays Goat Rodeo) adopters. As Scala and Lift are still very young adoption is vital and hence I would like to know, what you suggest: How could we only use Option *and* get something like Failure? Any ideas? Heiko On 26 February 2010 05:40, Daniel Spiewak wrote: > I'm sure this has been discussed before, but I'm curious as to the > rationale for the Box ADT. I'm most distressed by the fact that it > seems to be masquerading as a drop-in Option replacement, and yet the > mathematical properties of the ADT are widely divergent. What's more, > the API is very, very different, leading to a great deal of confusion > whenever I'm working with code which touches both ADTs (as I often > do). Things like `or` vs `orElse`, `open_!` vs `get` and so on are > very confusing. The implicit conversion Box[A] => Option[A] doesn't > help either, since it means I can easily forget and use Option methods > on Box values, accidentally triggering a conversion. > > The whole `or` vs `orElse` thing is particularly annoying since I > spend a fair amount of time wading through research which discusses > the `orElse` function in its abstract monadic sense. Given the > standard nature of the name (dating back long before Scala), I'm > surprised that Box went with something else. > > I'm sure there are good reasons for all of this, I would just like to > know what they are. :-) > > Daniel > > -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to lift...@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscr...@googlegroups.com > . > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en. > > -- Heiko Seeberger Company: weiglewilczek.com Blog: heikoseeberger.name Follow me: twitter.com/hseeberger OSGi on Scala: scalamodules.org Lift, the simply functional web framework: liftweb.net -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Reasoning Behind Box
I'm assuming you know that it has a third, Failure state, and you're asking about the names. I guess open_! is in keeping with the metaphor of a box (or originally, a can). The _! is Lift's way of saying, Danger! And I guess 'or' is just shorter. (Lift tends to put practicality before academic functionalness etc.) - Daniel Spiewak wrote: I'm sure this has been discussed before, but I'm curious as to the rationale for the Box ADT. I'm most distressed by the fact that it seems to be masquerading as a drop-in Option replacement, and yet the mathematical properties of the ADT are widely divergent. What's more, the API is very, very different, leading to a great deal of confusion whenever I'm working with code which touches both ADTs (as I often do). Things like `or` vs `orElse`, `open_!` vs `get` and so on are very confusing. The implicit conversion Box[A] => Option[A] doesn't help either, since it means I can easily forget and use Option methods on Box values, accidentally triggering a conversion. The whole `or` vs `orElse` thing is particularly annoying since I spend a fair amount of time wading through research which discusses the `orElse` function in its abstract monadic sense. Given the standard nature of the name (dating back long before Scala), I'm surprised that Box went with something else. I'm sure there are good reasons for all of this, I would just like to know what they are. :-) Daniel -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Reasoning Behind Box
I'm sure this has been discussed before, but I'm curious as to the rationale for the Box ADT. I'm most distressed by the fact that it seems to be masquerading as a drop-in Option replacement, and yet the mathematical properties of the ADT are widely divergent. What's more, the API is very, very different, leading to a great deal of confusion whenever I'm working with code which touches both ADTs (as I often do). Things like `or` vs `orElse`, `open_!` vs `get` and so on are very confusing. The implicit conversion Box[A] => Option[A] doesn't help either, since it means I can easily forget and use Option methods on Box values, accidentally triggering a conversion. The whole `or` vs `orElse` thing is particularly annoying since I spend a fair amount of time wading through research which discusses the `orElse` function in its abstract monadic sense. Given the standard nature of the name (dating back long before Scala), I'm surprised that Box went with something else. I'm sure there are good reasons for all of this, I would just like to know what they are. :-) Daniel -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.