tag:blogger.com,1999:blog-2447174102813539049.post3023648275949867996..comments2024-03-19T00:18:06.964-07:00Comments on Room 101: TuplesGilad Brachahttp://www.blogger.com/profile/17934280339206214042noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-2447174102813539049.post-51065069616922777312022-09-28T06:23:24.433-07:002022-09-28T06:23:24.433-07:00I also miss having tuples in java. As others have ...I also miss having tuples in java. As others have noted you can obviously make you own little implementation of them. Functional libraries such as vavr and jool also provide a version of their own. However I wanted to add my 5 cents that I had an 'aha' moment the other day when I realized lambdas are a perfectly valid replacement for tuples out of the box. for example if you just want to return multiple values from a function without creating a special class for that you can<br /><br />public static <T1,T2> Consumer<BiConsumer<String,T2>> getDefaultValueWithMsgSillyExample(Map<T1,T2> map, T1 key, T2 defaultValue){<br /> return map.containsKey(key)? func -> func.accept("I found the key you asked for!", map.get(key)):<br /> func -> func.accept("The key you asked for wasn't in the map, here is a default value", defaultValue);<br />}<br /><br /><br />Since this still looks a bit clunky you can define an interface with a static factory<br /><br /><br />@FunctionalInterface<br />public interface Tuple2<T1,T2> extends Consumer<BiConsumer<T1, T2>> {<br /> static <T1,T2> Tuple2<T1, T2> tuple(T1 t1, T2 t2){<br /> return func -> func.accept(t1,t2);<br /> }<br /><br /> static <U1,U2> U1 getFirst(Tuple2<U1,U2> tuple){<br /> Box<U1> box = new Box<>();<br /> tuple.accept((x,y)->box.setItem(x));<br /> return box.getItem();<br /> }<br /><br /> static <U1,U2> U2 getSecond(Tuple2<U1,U2> tuple){<br /> Box<U2> box = new Box<>();<br /> tuple.accept((x,y)->box.setItem(y));<br /> return box.getItem();<br /> }<br /><br />}<br /><br />and then the above example shrinks to <br /><br />public static <T1,T2> Tuple2<String,T2> getDefaultValueWithMsgSillyExample(Map<T1,T2> map, T1 key, T2 defaultValue){<br /> return map.containsKey(key)? func -> func.accept("I found the key you asked for!", map.get(key)):<br /> func -> func.accept("The key you asked for wasn't in the map, here is a default value", defaultValue);<br />}<br /><br /><br />and then you can just use it:<br /><br />public static void main(String[] args) {<br /> Tuple2<String, Integer> tuple = getDefaultValueWithMsgSillyExample(new HashMap<>(), 10, 100);<br /> String msg = getFirst(tuple);<br /> Integer value = getSecond(tuple);<br />}<br /><br />and since lambda variables are automatically unpacked you almost get an equivalent of python's tuple unpacking feature:<br /><br />public static void main(String[] args) {<br /> Tuple2<String, Integer> tuple = getDefaultValueWithMsgSillyExample(new HashMap<>(), 10, 100);<br /><br /> tuple.accept((message, value) -> {<br /> // use the unpacked tuple as you wish while you're in this scope..<br /> System.out.println(message + ":" + value);<br /> });<br />}<br /><br /><br /><br />you can define similar overloads for 3,4,etc' type variables if you wish<br /><br />The only problem with tuples for me is that the fields are not named so if you have several fields with the same type you might mix them up at the call site. if only java would have supported typedefs, this could have been taken care of too..<br /><br />Nadav Chttps://www.blogger.com/profile/03000616744071817112noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-17665582154691713522022-09-28T06:15:23.319-07:002022-09-28T06:15:23.319-07:00This comment has been removed by the author.Nadav Chttps://www.blogger.com/profile/03000616744071817112noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-65402081944494950572022-09-28T06:12:30.660-07:002022-09-28T06:12:30.660-07:00This comment has been removed by the author.Nadav Chttps://www.blogger.com/profile/03000616744071817112noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-73079444941205106602010-03-19T20:28:06.568-07:002010-03-19T20:28:06.568-07:00I have rolled out my own Tuple mini-lib and I use ...I have rolled out my own Tuple mini-lib and I use it all the time.<br /><br />http://paste.pocoo.org/show/191712/Zimbabwe vgtjbkjkijhttps://www.blogger.com/profile/10950240139175717925noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-20310292412929636902009-07-06T18:49:56.600-07:002009-07-06T18:49:56.600-07:00This comment has been removed by a blog administrator.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-44651988677341108792008-01-09T06:09:00.000-08:002008-01-09T06:09:00.000-08:00how about...class Tuple { private list = null; T...how about...<BR/><BR/>class Tuple {<BR/> private list = null;<BR/> Tuple(Object... list) {<BR/> this.list = list;<BR/> }<BR/> public Object get(int idx) {<BR/> return this.list[idx];<BR/> }<BR/>}Mobushttps://www.blogger.com/profile/13066747557576537014noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-43616563505376122682007-09-11T11:19:00.000-07:002007-09-11T11:19:00.000-07:00Isn't a Set (post-generics) a poor man's tuple?Isn't a Set (post-generics) a poor man's tuple?fundouhttps://www.blogger.com/profile/00034522420527031480noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-58470782079977081352007-07-04T07:02:00.000-07:002007-07-04T07:02:00.000-07:00Must also mention Erlang with first class tuples. ...Must also mention Erlang with first class tuples. <BR/><BR/>Come to think of it, Erlang also has pure message-passing share-nothing actor formalism, and hotswappable code, so it ticks most of your boxes - shame about the Unicode thing :(Mikhail Francohttps://www.blogger.com/profile/03481680831801564473noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-35187687066386645382007-05-22T17:44:00.000-07:002007-05-22T17:44:00.000-07:00You can write an API that goes a long way to provi...You can write an API that goes a long way to providing Tuples in Java:<BR/><BR/>public class Tuples {<BR/>__public static class Tuple1< E1 > {<BR/>____public final E1 e1;<BR/>____Tuple1( final E1 e1 ) { this.e1 = e1; }<BR/>____// etc.<BR/>__}<BR/>__public static < E1 > Tuple1< E1 > t( final E1 e1 ) {<BR/>____return new Tuple1( e1 );<BR/>__}<BR/><BR/>__public static class Tuple2< E1, E2 > extends Tuple1< E1 > {<BR/>____public final E2 e2;<BR/>____Tuple1( final E1 e1, final E2 e2 ) {<BR/>______super( e1 );<BR/>______this.e2 = e2;<BR/>____}<BR/>____// etc.<BR/>__}<BR/>__public static < E1, E2 > Tuple2< E1, E2 > t( final E1 e1, final E2 e2 ) {<BR/>____return new Tuple2( e1, e2 );<BR/>__}<BR/><BR/>__// etc.<BR/>}<BR/><BR/>If Tuples is imported statically then you can have the construct t( ... ) to create tuples.hlovatthttps://www.blogger.com/profile/07048859648718746436noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-6777057243248889562007-05-17T18:57:00.000-07:002007-05-17T18:57:00.000-07:00Indeed, there is no difference between array liter...Indeed, there is no difference between array literals and tuples in a dynamically typed setting - provided the array literals are unrestricted. <BR/><BR/>For example, in Smalltalk, they are required to be compile time constants. Some dialects support tuples though, and the thingto do is chukj the old array literals and only use the tuples.Gilad Brachahttps://www.blogger.com/profile/17934280339206214042noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-40556640681658762032007-05-17T18:52:00.000-07:002007-05-17T18:52:00.000-07:00This post gave me an 'a-ha' moment because I've be...This post gave me an 'a-ha' moment because I've been wanting tuples for years and never knew they existed. Thanks. <BR/><BR/>But I have a question: In a weakly typed language, what is the difference between a tuple and an array? I don't see one.Hamlet D'Arcyhttps://www.blogger.com/profile/04008870357169725586noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-55908157048627346522007-04-17T02:57:00.000-07:002007-04-17T02:57:00.000-07:00Tuples are doing a nice job in Eiffel.Tuples are doing a nice job in Eiffel.Ogi Pishevhttps://www.blogger.com/profile/14680315556911026742noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-61770304097934034622007-03-11T20:53:00.000-07:002007-03-11T20:53:00.000-07:00Oops, the link to "good tuple support" above is br...Oops, the link to "good tuple support" above is broken; it should have been to <A HREF="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html" REL="nofollow">here</A>.drumhellerhttps://www.blogger.com/profile/10083484315735524107noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-82781291313646049572007-03-11T09:00:00.000-07:002007-03-11T09:00:00.000-07:00And I'd like to point out that Boost effectively p...And I'd like to point out that Boost effectively provides C++ with <A HREF="" REL="nofollow" HREF=HTTP://WWW.BOOST.ORG/LIBS/TUPLE/DOC/TUPLE_USERS_GUIDE.HTML>good tuple support</A>, albeit as a template library not a core language element.drumhellerhttps://www.blogger.com/profile/10083484315735524107noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-74523051620593479292007-03-11T05:52:00.000-07:002007-03-11T05:52:00.000-07:00Just felt compelled to point you towards the D pro...Just felt compelled to point you towards the <A HREF="http://www.digitalmars.com/d/" REL="nofollow">D programming language</A> which grew basic support for tuples several versions ago. Sadly, we don't have multi-value returns yet, although they are in the works. The D community can always use more smart people to help steer the language :)Dkhttps://www.blogger.com/profile/02909587337938463354noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-21240154817238503372007-03-01T05:23:00.000-08:002007-03-01T05:23:00.000-08:00You are right about type-safety and concurrency pr...You are right about type-safety and concurrency problems that mutability causes. But I also look at it in a different and very important way -- language features shall strive to be orthogonal even though it is never perfectly possible in a real programming language that also has to be convenient. <BR/><BR/>If we have both mutability and tuple field access, then people would ask -- why don't you simply write a class for that? How do I choose between a class and a tuple when I write my code? <BR/><BR/>Both strict immutability and field access by pattern matching only make tuples so clearly distinct from classes, that those kinds of questions will rarely arise in practice.elizarovhttps://www.blogger.com/profile/06339534234190675498noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-83476041324374267812007-02-28T10:28:00.000-08:002007-02-28T10:28:00.000-08:00I don't think that mutability is harmful per-se. T...I don't think that mutability is harmful per-se. The problem with mutability (in this context) is that it compromises type safety/covariant subtyping (and also thread safety). I don't understand why tuple field access may be harmful. <BR/><BR/>On a more general note, most features of a language do not add expressive power (you probably cannot be more powerful than a Turing machine). Thus, the claim that a feature only lets you "solve many real-life problems in a nice and convenient way" is true in almost any language design discussion.Anonymoushttps://www.blogger.com/profile/15900841850889743147noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-30303016840850101202007-02-27T05:32:00.000-08:002007-02-27T05:32:00.000-08:00Mutability and explicit tuple field access are bot...Mutability and explicit tuple field access are both not needed and can be even considered harmful. In OO languages there are classes which have both features. Tuples should not try to subsume other features, but are a nice light-weight addition to virtually any language. They do not really add power, but let you solve many real-life problems in a nice and convenient way.<BR/><BR/>Gilad mentioned that his tuples proposal was supposed to subsume varargs. I think that I saw this proposal somewhere on SDN, but, AFAIR, it was not as convenient as "true" varargs. You don't have to be using extra braces for true varargs support which Java now enjoys.<BR/><BR/>However, varargs can be considered as a feature that subsumes "multiple argument" functions (i.e. more than one argument), like it is commonly done in functional languages.elizarovhttps://www.blogger.com/profile/06339534234190675498noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-29015750285844083542007-02-26T08:09:00.000-08:002007-02-26T08:09:00.000-08:00I totally agree with the need for tuples. The prob...I totally agree with the need for tuples. The problem of "multiple return values" is indeed a pain.<BR/><BR/>Two comments:<BR/><BR/>First, to emphasize your point, in the context of tuples, there are three important properties:<BR/>- Static type safety<BR/>- Covariant subtyping<BR/>- Mutability<BR/><BR/>The catch is that the three cannot be supported simultaneously: one of these properties needs to be dropped. It seems that giving up mutability is, indeed, the best compromise.<BR/><BR/>Second, there is the issue of tuple field access. The two obvious options are: (1) by-name, (2) by-position. Elizarov also suggests pattern matching for this purpose.Anonymoushttps://www.blogger.com/profile/15900841850889743147noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-39082656256983388782007-02-26T05:28:00.000-08:002007-02-26T05:28:00.000-08:00This is a pretty obvious point, but nonetheless a ...This is a pretty obvious point, but nonetheless a point worth spelling out at least every year ;). You did not mention an other obvious benefit of tuples -- they let you swap two variable in _a_right_way_, that is: <BR/><BR/>x, y = y, x;<BR/><BR/>IMHO, the problem with Java is that it really should have supported tuples from the very start and it should really be supported inside JVM, since otherwise tuples implementation on top of existing JVM is quite costly and would be frowned upon. On the other hand, modification of JVM spec to support tuples is now extremely costly, too, since many other specs (JNI, JVMxI, etc) have been build upon JVM and all they heavily rely on absence of tuples in JVM.elizarovhttps://www.blogger.com/profile/06339534234190675498noreply@blogger.comtag:blogger.com,1999:blog-2447174102813539049.post-6368445416054709562007-02-25T11:01:00.000-08:002007-02-25T11:01:00.000-08:00Nice to read you every now and then. I so totally ...Nice to read you every now and then. I so totally agree with you on tuples. Every language should have them.Fatih Coşkunhttps://www.blogger.com/profile/17778808022836201232noreply@blogger.com