[Lift] Re: Reasoning Behind Box
Either would be the purely stdlib way to go, and Naftoli is right that it would be a lot more verbose. I would argue that the difference isn't *so* substantial if you sprinkle in a type alias and some implicit conversions (so that you can map/flatMap/filter over something of type Either[Option[A], String]). I am aware of the Failure case, and that's why I argue that Box *isn't* a drop-in Option replacement. API naming differences are inconsequential, but adding another case to the ADT is a pretty dramatic difference. However, Lift seems to use Box *everywhere*, even in places where it is only using it as if it were Option. Daniel On Feb 26, 1:17 am, Heiko Seeberger heiko.seeber...@googlemail.com wrote: On 26 February 2010 08:09, Naftoli Gugenheim naftoli...@gmail.com 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.
[Lift] Re: Reasoning Behind Box
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. A valid point. I would argue that this is the correct way to solve this problem, but it's obviously not the cleanest. 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.) +1 For the record, the Option name comes from ML, while Maybe comes from Haskell (and its heritage). As I recall, Martin is a great fan of ML, which is why most of Scala's functional features are heavily inspired by that language. In fact, the only functional feature I can think of which Scala got from Haskell would be typeclasses. - 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? Agreed. This is maybe an education thing. My biggest problem with open_! is the highly unidiomatic use of mixed alpha-symbolic method name. Yes, I know Lift does it everywhere, but I can't think of any other Scala library which does the same. Maybe I'm being too pedantic, but I cringe every time I see it in my code. :-) - orElse orElse orElse... who named this method. In terms of method naming the Else is a useless waste of 4 characters... the camel case takes the eye away from the things that are being tested... there's no reason for the Else part. The name for this method was devised a *long* time ago. I don't remember exactly when, but it was a part of research examining monads in the abstract mathematical sense. As a result, the goal was to name the function something which would be unambiguous in the proverbial global context. They probably thought of or, but that's not specific enough. Thus, orElse. Since almost all languages which have monads also use Hindley-Milner type inference, it's not surprising that the name has stuck. Scala is really one of the few languages which *can* go with something else. I proposed to the Scala team that they include the Failure subclass as part of Option. They declined. Mainly for two practical reasons: thousands of Some/None pattern matches would be broken and Martin has always wanted to optimize Option at the compiler level to be ref/null so there would be no necessary boxing of Options. I took another run at Martin with the idea 14 months ago when 2.8 was just on the drawing board and Martin once again declined. I have to say, I'm with Martin on this one. Most FP trained folks who have looked at Box have vomited over the mathematical differences between Option and Box. Tony Morris is the most notable example of this... he was so unable to control his rage at the abomination that is Box that we had to ban him from the Lift list (he's the first of two people that share that dubious honor). I'm in rather interesting company, since I had a similar reaction when I first saw Box. Maybe not quite so violent, but in that general vein. To be clear, I have absolutely no problem with it as a separate ADT unto itself. In fact, were I in your shoes, I may have even come up with something similar. However, I would have made it a proper ADT with four instances: Full(...), Empty,
[Lift] Re: Reasoning Behind Box
It sometimes seems to me that people are view-ing Option as an absolute term - a complete Maybe monad that everyone should obey. Yeah, that's pretty much it. :-) Saying that you have a replacement Option with totally different instances is like telling me that you have a new definition for a derivative. Maybe/Option are just implementations of the same abstract mathematical concept (like two different ways of writing the *same* definition of a derivative). Box is something which is obviously inspired by the Maybe monad, but seems to have gone in a totally new direction with it. I'm not saying that direction is bad, but it's certainly not anything like Maybe. It's like looking at the problem of computing instantaneous rate of change and coming up with a technique which maps things into a different complexity domain. Your results may be valid, but you're certainly not going to end up with differential calculus as we know it. 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.
[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.
[Lift] Re: User Presence Heartbeat
We can make fixes to the 1.0.x branch for you, but I am reluctant to make changes to the 1.0 version. Very understandable. We'll just bump up to the 1.0.2 release. That jump has been on the back burner for a while, so it's good to get an excuse to push it through. :-) You might look into having your session management system let Lift know that the session is going down. Lift *should* be tied to the container's session and if it's not working, please get us a repro case and we'll fix it. Looking into it now. It's also possible that Spring Security isn't killing off the session properly, in which case Lift is more than justified in hanging onto whatever information it has left. If it turns out that the session is dying but Lift still isn't firing Unlisten on its own, then I'll do what I can to get you a reproducible test case. Time is a little tight right now though, so I may not be able to do much more than report the bug in a case-less state. Is this an issue that needs to be solved this week? If not, I'll have more time next week and can putter around with Jetty and see what I can learn about what it does with comet, NIO, etc. and see if there's a better way to give you what you need. The sooner the better, but we understand that you have other things to do. We're going to forge ahead with the Listen/Unlisten trick coupled with some extra hooks in Spring Security working under the assumption that we'll be able to make it solid enough for now. If and when you find a better way to do this, we'll switch to that technique moving forward. So in other words, feel free to putter as soon as you get the chance! We would certainly appreciate anything you can come up with. 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.
[Lift] Re: User Presence Heartbeat
This seems to work very nicely. Well, it gives me lots of spurious events, but a little bit of filtering based on active ListenerId(s) and I'm golden. Unfortunately, I've already run into two main problems: * It seems to be somewhat non-deterministic as to whether or not every listener is closed when the browser is shut down (Firefox 3.6). It's possible that just one listener is remaining active (hasn't been Unlisten'ed), which would prevent my presence system from firing. Is this to be expected? Do I just need to wait a little longer for the connection to time out? * The Unlisten event does not *ever* seem to fire when the user logs out. The logout action redirects the user back to the login page, which obviously wouldn't have a long-poll. Nevertheless, my system still thinks the logged-out user is active. It's possible that I'm filtering something or perhaps associating the event wrong; it would depend on whether session var changes propagate prior to the Unlisten event. Any ideas here? Daniel On Jan 12, 12:46 pm, David Pollak feeder.of.the.be...@gmail.com wrote: I'm kind swamped today, but the simplest thing you can do is: private def notifyListen = { MyUserThingy.gotAListenEventFor(User.currentUser) false } private def notifyUnlisten = { MyUserThingy.gotAnUnlistenEventFor(User.currentUser) false } override def highPriority = { case Listen(_, _, _) if notifyListen = () case Unlisten(_) if notifyUnlisten = () } Each time the browser registers as a listener, you'll get a notification (the beginning of the long poll). Each time the browser unregisters as a listener (the end of the long poll), you'll get a notification. This stuff is kinda internal and may change (although there's no plans to change the Listen/Unlisten logic). On Tue, Jan 12, 2010 at 10:25 AM, Daniel Spiewak djspie...@gmail.comwrote: We're already using the Comet support within Lift quite extensively across the board. There are very, very few pages in our application which do not have a CometActor embedded in them at some level of nesting. Daniel On Jan 12, 12:08 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: You are already using Comet, or just Lift? - Daniel Spiewakdjspie...@gmail.com wrote: I'm looking to implement a user presence feature (think: Facebook or Gmail chat) in a Lift 1.0 application. Ideally, I would like to avoid adding extraneous connections. Is it possible to hook into the Lift Comet heartbeat which is already in use across our system? I've looked at the source for CometActor, and it's just a little too obfuscated for me to figure this one out on my own. :-) Alternatively, has anyone else implemented this sort of system in Lift? If so, how did you go about it? Any tips from the well- informed? 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.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group athttp:// 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.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- 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] User Presence Heartbeat
I'm looking to implement a user presence feature (think: Facebook or Gmail chat) in a Lift 1.0 application. Ideally, I would like to avoid adding extraneous connections. Is it possible to hook into the Lift Comet heartbeat which is already in use across our system? I've looked at the source for CometActor, and it's just a little too obfuscated for me to figure this one out on my own. :-) Alternatively, has anyone else implemented this sort of system in Lift? If so, how did you go about it? Any tips from the well- informed? 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.
[Lift] Re: User Presence Heartbeat
We're already using the Comet support within Lift quite extensively across the board. There are very, very few pages in our application which do not have a CometActor embedded in them at some level of nesting. Daniel On Jan 12, 12:08 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: You are already using Comet, or just Lift? - Daniel Spiewakdjspie...@gmail.com wrote: I'm looking to implement a user presence feature (think: Facebook or Gmail chat) in a Lift 1.0 application. Ideally, I would like to avoid adding extraneous connections. Is it possible to hook into the Lift Comet heartbeat which is already in use across our system? I've looked at the source for CometActor, and it's just a little too obfuscated for me to figure this one out on my own. :-) Alternatively, has anyone else implemented this sort of system in Lift? If so, how did you go about it? Any tips from the well- informed? 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 athttp://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] Re: User Presence Heartbeat
Sweet, that looks like exactly what I need! I'll post back here if that doesn't work properly. Daniel On Jan 12, 12:46 pm, David Pollak feeder.of.the.be...@gmail.com wrote: I'm kind swamped today, but the simplest thing you can do is: private def notifyListen = { MyUserThingy.gotAListenEventFor(User.currentUser) false } private def notifyUnlisten = { MyUserThingy.gotAnUnlistenEventFor(User.currentUser) false } override def highPriority = { case Listen(_, _, _) if notifyListen = () case Unlisten(_) if notifyUnlisten = () } Each time the browser registers as a listener, you'll get a notification (the beginning of the long poll). Each time the browser unregisters as a listener (the end of the long poll), you'll get a notification. This stuff is kinda internal and may change (although there's no plans to change the Listen/Unlisten logic). On Tue, Jan 12, 2010 at 10:25 AM, Daniel Spiewak djspie...@gmail.comwrote: We're already using the Comet support within Lift quite extensively across the board. There are very, very few pages in our application which do not have a CometActor embedded in them at some level of nesting. Daniel On Jan 12, 12:08 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: You are already using Comet, or just Lift? - Daniel Spiewakdjspie...@gmail.com wrote: I'm looking to implement a user presence feature (think: Facebook or Gmail chat) in a Lift 1.0 application. Ideally, I would like to avoid adding extraneous connections. Is it possible to hook into the Lift Comet heartbeat which is already in use across our system? I've looked at the source for CometActor, and it's just a little too obfuscated for me to figure this one out on my own. :-) Alternatively, has anyone else implemented this sort of system in Lift? If so, how did you go about it? Any tips from the well- informed? 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.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group athttp:// 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.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Lift, the simply functional web frameworkhttp://liftweb.net Beginning Scalahttp://www.apress.com/book/view/1430219890 Follow me:http://twitter.com/dpp Surf the harmonics -- 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.