Prev: Pocket Lisp Machine
Next: Next Generation of Language
From: Jon Harrop on 7 Oct 2006 02:17 Thomas A. Russ wrote: > If you want to, say, write code > to find equational roots using the Newton method, why do you need to > care whether the equation returns fixnum, bignum, single floats or > double floats? Precision and computational complexity. > Just because there is compile-time > type safety doesn't help you when there is interactive input. No. Look at the OCaml top-level, for example. > Nor does > it protect you against algorithmic bugs, Static type checking facilitates pattern match exhaustiveness checking, for example. > Well, if we need to argue generalizations, then how about dynamic > languages always let you write your code faster than statically typed > languages? I see no evidence of that. > Besides, a statically typed language is not always superior in execution > speed. Can you give an example of a program written in a dynamically typed language for which there is no faster equivalent written in a statically typed language? > If what you are doing requires type dispatch, the compiler, > especially if it has specially-tweaked mechanisms for this is probably a > lot more efficient than whatever you have to add to your program to get > the same effect and flexibility. (Greenspun's 10th rule, etc.) Maybe. Can you give an example? >> # type number = Int of int | Float of float | Big of Big_int.big_int;; >> type number = Int of int | Float of float | Big of Big_int.big_int >> # let n = Float 9.4;; >> val n : number = Float 9.4 >> # match n with >> | Float n -> print_string "It is a float" >> | Int n -> print_string "It is an integer" >> | Big n -> print_string "It is a big number";; >> => It is a float >> - : unit = () > > So why would this sort of construct be any more efficient than a dynamic > dispatch, when the runtime system knows it needs to handle this? It is probably less efficient. It is certainly more verbose. Very few ML programs use a numeric tower, e.g. very few OCaml programs use the numeric tower provided by the Num module. -- Dr Jon D Harrop, Flying Frog Consultancy Objective CAML for Scientists http://www.ffconsultancy.com/products/ocaml_for_scientists
From: Javier on 7 Oct 2006 08:17 Thomas A. Russ ha escrito: > "Javier" <javuchi(a)gmail.com> writes: > > > Rahul Jain ha escrito: > > > > > > Yes, but how do _I_ know when I need to use bignums or not? > > > > You must know, you are a programmer. Even in Lisp you must know the > > type you are using for every variable. > > Actually, this is not true in the case of certain distinctions such as > the (arbitrary) one between FIXNUMs and BIGNUMs. Yes, but you still need to know what type are you using for most of the variables. For example you must know that you are using a list, and cannot trat it as if it were an integer, or you'll get an error. > > # type number = Int of int | Float of float | Big of Big_int.big_int;; > > type number = Int of int | Float of float | Big of Big_int.big_int > > # let n = Float 9.4;; > > val n : number = Float 9.4 > > # match n with > > | Float n -> print_string "It is a float" > > | Int n -> print_string "It is an integer" > > | Big n -> print_string "It is a big number";; > > => It is a float > > - : unit = () > > So why would this sort of construct be any more efficient than a dynamic > dispatch, when the runtime system knows it needs to handle this? It is not more efficent, but it is true that you only use dispatch when you need, while in Lisp the compiler is probably doing it almost all the time. CL-USER> (defun sum-to-nums (a b) (+ a b)) SUM-TO-NUMS CL-USER> (disassemble 'sum-to-nums) ; 11CB50A1: 8B55F4 MOV EDX, [EBP-12] ; no-arg-parsing entry point ; A4: 8B7DF0 MOV EDI, [EBP-16] ; A7: E894B034EF CALL #x1000140 ; GENERIC-+ ; AC: 7302 JNB L0 ; AE: 8BE3 MOV ESP, EBX ; B0: L0: 8D65F8 LEA ESP, [EBP-8] ; B3: F8 CLC ; B4: 8B6DFC MOV EBP, [EBP-4] ; B7: C20400 RET 4 It is doing a call to the generic-+, which I don't have acess to it, but + outputs this code: CL-USER> (disassemble '+) ; 106DFB68: .ENTRY +(&REST ARGS) ; (FUNCTION ; # *) ; B80: 8F45F8 POP DWORD PTR [EBP-8] ; B83: E337 JECXZ L1 ; B85: 8D5DE0 LEA EBX, [EBP-32] ; B88: 29CB SUB EBX, ECX ; B8A: 8BE3 MOV ESP, EBX ; B8C: 8BD9 MOV EBX, ECX ; B8E: 83E90C SUB ECX, 12 ; B91: 7612 JBE L0 ; B93: 57 PUSH EDI ; B94: 56 PUSH ESI ; B95: 8D7C2408 LEA EDI, [ESP+8] ; B99: 8BF5 MOV ESI, EBP ; B9B: 29DE SUB ESI, EBX ; B9D: C1E902 SHR ECX, 2 ; BA0: FC CLD ; BA1: F2 REPNE ; BA2: A5 MOVSD ; BA3: 5E POP ESI ; BA4: 5F POP EDI ; BA5: L0: 8BCB MOV ECX, EBX ; BA7: 8955DC MOV [EBP-36], EDX ; BAA: 83F904 CMP ECX, 4 ; BAD: 7410 JEQ L2 ; BAF: 897DD8 MOV [EBP-40], EDI ; BB2: 83F908 CMP ECX, 8 ; BB5: 7408 JEQ L2 ; BB7: 8975D4 MOV [EBP-44], ESI ; BBA: EB03 JMP L2 ; BBC: L1: 8D65E0 LEA ESP, [EBP-32] ; BBF: L2: 894DF0 MOV [EBP-16], ECX ; BC2: 8B4DF0 MOV ECX, [EBP-16] ; BC5: 8D740CFC LEA ESI, [ESP+ECX-4] ; BC9: BB0B000008 MOV EBX, 134217739 ; BCE: E35F JECXZ L7 ; BD0: 8D144D00000000 LEA EDX, [ECX*2] ; BD7: 800D2403000804 OR BYTE PTR [#x8000324], 4 ; unboxed_region ; BDE: 0315D0BB3100 ADD EDX, [#x31BBD0] ; _boxed_region ; BE4: 3B15D4BB3100 CMP EDX, [#x31BBD4] ; boxed_region ; BEA: 7607 JBE L3 ; BEC: E80F4393EF CALL #x13F00 ; _alloc_overflow_edx ; BF1: EB12 JMP L4 ; BF3: L3: 3315D0BB3100 XOR EDX, [#x31BBD0] ; _boxed_region ; BF9: 3115D0BB3100 XOR [#x31BBD0], EDX ; _boxed_region ; BFF: 3315D0BB3100 XOR EDX, [#x31BBD0] ; _boxed_region ; C05: L4: 8D5203 LEA EDX, [EDX+3] ; C08: C1E902 SHR ECX, 2 ; C0B: FD STD ; C0C: 8BDA MOV EBX, EDX ; C0E: EB06 JMP L6 ; C10: L5: 83C208 ADD EDX, 8 ; C13: 8952F9 MOV [EDX-7], EDX ; C16: L6: AD LODSD ; C17: 8942FD MOV [EDX-3], EAX ; C1A: E2F4 LOOP L5 ; C1C: C742010B000008 MOV DWORD PTR [EDX+1], 134217739 ; C23: 80352403000804 XOR BYTE PTR [#x8000324], 4 ; unboxed_region ; C2A: 7403 JEQ L7 ; C2C: 0F0B09 BREAK 9 ; pending interrupt trap ; C2F: L7: 81FB0B000008 CMP EBX, 134217739 ; C35: 745A JEQ L14 ; C37: 8B4B01 MOV ECX, [EBX+1] ; C3A: 8B53FD MOV EDX, [EBX-3] ; C3D: F6C203 TEST DL, 3 ; C40: 740F JEQ L8 ; C42: 8BC2 MOV EAX, EDX ; C44: 2407 AND AL, 7 ; C46: 3C07 CMP AL, 7 ; C48: 753A JNE L13 ; C4A: 8A42F9 MOV AL, [EDX-7] ; C4D: 3C22 CMP AL, 34 ; C4F: 7733 JNBE L13 ; C51: L8: EB1F JMP L11 ; C53: L9: 8BC1 MOV EAX, ECX ; C55: 2407 AND AL, 7 ; C57: 3C03 CMP AL, 3 ; C59: 753D JNE L15 ; C5B: 8BC1 MOV EAX, ECX ; C5D: 8B4001 MOV EAX, [EAX+1] ; C60: 8945F4 MOV [EBP-12], EAX ; C63: 8B79FD MOV EDI, [ECX-3] ; C66: E8D50492F0 CALL #x1000140 ; GENERIC-+ ; C6B:
From: Javier on 7 Oct 2006 09:07 Thomas A. Russ ha escrito: > > In respect to word size, you are right, dynamic ilanguagges allows you > > to write less and more standard code. But the cost of this is that the > > rest of the system may be unsafe if you don't declare things. > > Well, safety is always relative. Just because there is compile-time > type safety doesn't help you when there is interactive input. Nor does > it protect you against algorithmic bugs, divide by zero (unless you make > rather heroic assumptions about the cleverness of the type system and > what it can figure out.) I'll put here an example: (defun sum-list (lst) (cond ((null lst) nil) (t (+ (car lst) (sum-list (cdr lst)))))) This compiles on SBCL without give up a single warning. But if you try to exec it: CL-USER> (sum-list (list 1 2 3)) => Error Argument Y is not a NUMBER: NIL [Condition of type SIMPLE-TYPE-ERROR] If you try to write the same function on ML: # let rec sum_list lst = match lst with []->[] | h::t -> h + (sum_list t);; Characters 67-83: | h::t -> h + (sum_list t);; ^^^^^^^^^^^^^^^^ => This expression has type int but is here used with type 'a list The compiler inmediatly gives you an error and do not let you to compile and use it. This error may be self evident as it is very simple. But imagine the same kind of error on a big system, or in a function which is 100 lines long with several conditions. On Lisp, your application may run fine for ages until some day the bug appear. Just imagine what would happen If the life of people depends on this kind of application (for example for controlling train or flight traffics), or if it is used to manage bank accounts...
From: Stefan Nobis on 7 Oct 2006 12:23 "Javier" <javuchi(a)gmail.com> writes: > This error may be self evident as it is very simple. Yes. > But imagine the same kind of error on a big system, or in a function > which is 100 lines long with several conditions. That's what Thomas tried to say: In these cases there are so many ways to put errors in your code of which only (very) few can be caught be a static type system. So you have to do something about the other types of errors anyway and you can't rely only on your static type system. In fact the difference is not very big (in Lisp you have to do a little bit more to also catch type errors but the hard work are test cases or the like for all the other bugs) but on the other hand Lisp is much more flexible and fun -- so why bother with static type systems. :) -- Stefan.
From: Javier on 7 Oct 2006 14:34
Stefan Nobis ha escrito: > "Javier" <javuchi(a)gmail.com> writes: > > > This error may be self evident as it is very simple. > > Yes. > > > But imagine the same kind of error on a big system, or in a function > > which is 100 lines long with several conditions. > > That's what Thomas tried to say: In these cases there are so many ways > to put errors in your code of which only (very) few can be caught be a > static type system. So you have to do something about the other types > of errors anyway and you can't rely only on your static type system. In fact it is not only the type system. :) For example, in ML the null keyword does not exist, and so nothing equivalent. Everything must have a correct value. The combination of static type checking and not null arithmetic becomes to a safer system. Your application may present incorrect solutions to the problems, but at least it is going to get running in most cases. > In fact the difference is not very big (in Lisp you have to do a > little bit more to also catch type errors but the hard work are test > cases or the like for all the other bugs) but on the other hand Lisp > is much more flexible and fun -- so why bother with static type > systems. :) Sure, there is probably more fun on Lisp (this is just a personal taste). I would like a mixture of both worlds. For example, I'd like Lisp to be strong in most cases (for example, to not allow to mix integers and lists), but still tolerant with compatible ones (for example, to mix bignums and integers). As far as I know, this doesn't exist at the moment. |