8 ms·
> If value is not a numeric type, square is not going to be happy. That is not necessarily true. In Common Lisp, with its generic-function based object system
by lisper 6y ago
> If value is not a numeric type, square is not going to be happy.
That is not necessarily true. In Common Lisp, with its generic-function based object system, you can extend the operation of any function at any time to cover new types. So, for example, one could define a method for SQUARE that operates on matrices.
> What thing that violates a type check would be "perfectly fine to do"?
(define (self-apply fn) (fn fn))
- adwn 6y ago> (define (self-apply fn) (fn fn)) Out of curiousity, what would be a practical application of this?
- lisper 6y agoSee: http://www.flownet.com/ron/lambda-calculus.html http://www.flownet.com/ron/lambda-calculus.html
- adwn 6y agoThat didn't answer my question. Let me rephrase it: When would you use (define (self-apply fn) (fn fn)) in an actual, real-life situation (outside of teaching lambda calculus)?
- kazinator 6y agoWithout additional arguments? Never. With additional arguments, it provides the function with access to itself. This could be used "under the hood" in an implementation to bootstrap the ability of named local functions to have themselves in scope, which is useful for writing ordinary recursion. Compilers and interpreters can achieve such a thing without any such jig like a Y combinator, because interpreters and compilers work with environments that are re-ified as objects. They are free to manipulate environments and evaluate/compile any piece of code in any environment they see fit.
- lisper 6y agoPersonally, I consider teaching the lambda calculus to be a real-life situation. Teaching the lambda calculus is no less real to me than any other part of my life. But OK, self-apply is not something you're likely to see in production code, and neither are Church numerals, which is where this problem shows up for real. But MAP, REDUCE, and APPLY are, and they all have the same problem as self-apply: their static types are infinite. This is a general problem with all static type systems. There are only two possibilities: either your type system is Turing complete or it is not. If it is not, then there are things that one might reasonably want to express that cannot be expressed, and if it is, then it is undecidable. Static typing is either constraining, or it is a Turing Tarpit (https://en.wikipedia.org/wiki/Turing_tarpit https://en.wikipedia.org/wiki/Turing_tarpit).
- adwn 6y ago> But MAP, REDUCE, and APPLY are, and they all have the same problem as self-apply: their static types are infinite. Huh? Any semi-decent static type system has no problems modeling higher-order functions, and static types can easily be infinite via parametric polymorphism ("generics"). > Static typing is either constraining, or it is a Turing Tarpit You're letting the perfect be the enemy of the good. Static type systems can be beneficial even when they don't solve every conceivable problem.
- lisper 6y ago> Static type systems can be beneficial I don't deny that. The problem is not with the idea, it's with the (usual) implementation, which is that if you don't appease the type-checker it won't let you run your program. I'm perfectly fine with a type checker that only gives me warnings but still allows me to run the code even if it isn't satisfied.
- rini17 6y agoMost implementations of Common Lisp prevent shadowing builtin symbols. You get compile/runtime error like "lock on COMMON-LISP package violated". So, unless author went to extra lengths to work around it, you can rely on the standard stuff like * when you read the code. Even for user-defined functions, it's not an usual practice to extend operation of any function (although again, it's kind of possible). There are CLOS generic functions for that.
- lisper 6y ago> Most implementations of Common Lisp prevent shadowing builtin symbols. So? Make your own package.
- rini17 6y agoWhat's your point? In CL it is trivial to determine both at compile and at runtime the package of all symbols involved. Same for generic methods, you can query the runtime which methods it is going to use for some concrete combination of parameters. Much easier than to determine how which overload of a C++ operator does the compiler/linker deem to fit in given context.
- lisper 6y agoMy point is that this: > Most implementations of Common Lisp prevent shadowing builtin symbols. is irrelevant. It's actually irrelevant for two reasons. First, the example under discussion was SQUARE which is not a CL builtin, and second, even if it was, you could just do this: Just make your own package and do: (in-package :my-package) (defmethod square ((n number)) (* n n)) Now you can extend SQUARE to work on things other than numbers. Or, to pick a more realistic example: (defmethod sqrt ((n number)) (cl:sqrt n))
- rini17 6y agoOh that's the misunderstanding, I was talking about overloading of the '*' operator and the consequent confusion, not overloading of 'square'.