Re: [q-lang-users] composing or lambda?
Brought to you by:
agraef
From: Albert G. <Dr....@t-...> - 2006-11-23 21:10:08
|
Eddie Rucker wrote: > I've go two lines in a program that computes stats on a file of surveys: > > addSurvey X Y = zipwith (zipwith (+)) X Y; > addSurveyId A = map Id A where Id = (mklist 0) . (#); > > where X and Y are two lists with a 1 in the position of the student > response, like [0,0,1,0,0], and each survey is a list of these lists. > > My question is: > Does the "where" in addSurveyId compute "(mklist 0) . (#)" once and use > the new function throughout the map operation? Or does map just put > "(mklist 0) .(#)" in front of each element in the list and then reduce? It doesn't actually matter because: - The arguments to map are evaluated before map does its thing, so assigning the function to a local variable is just a convenience but doesn't change the course of the computation (unless, of course, you'd refer to the same computed function twice, in which case a local variable definition helps to avoid its recalculation). - In this special case mklist 0 . (#) is already a normal form anyway, so it just evaluates to itself (as you can readily verify by entering the expression directly in the interpreter). In general you can think of (.) as being defined by (F.G) X = F (G X), so an expression involving (.) is reduced no earlier than the argument to the composed function is supplied. Note that evaluation is a bit different in Q than in ML or Haskell or any other modern-style FPL you might know, where equations are just syntactic sugar for lambdas and the lambda calculus is the basic machinery of computation. In such languages a closure will be created for each function expression, so a function expression will evaluate to something which is different from the expression itself. In Q it's all just term rewriting, so if a (function) expression like mklist 0 . (#) just stands for itself then that's fine with the interpreter. The interpreter doesn't care whether the expression denotes a function, in fact it doesn't even know what a function is! All it does is rewriting expressions according to the equations until it reaches a normal form. > Second question: > Which is better, readability and/or performance wise? > > "addSurveyId A = map (\X. mklist 0 (#X) A;" > > or > > "addSurveyId A = map ZeroVec A where ZeroVec = (mklist 0) . (#);" > > or > > "addSurveyId A = map (mklist 0 .(#)) A;" Readability-wise, I'd prefer the latter, but that's just personal preference. Performance-wise, there shouldn't be a big difference, although the first alternative might be a tad slower because it involves an extra builtin (lambda). In fact on my system I get: ==> #addSurveyId1 (mklist [0,0,1,0,0] 100000); stats 100000 0.94 secs, 400005 reductions, 700010 cells ==> #addSurveyId2 (mklist [0,0,1,0,0] 100000); stats 100000 0.89 secs, 400004 reductions, 700005 cells ==> #addSurveyId3 (mklist [0,0,1,0,0] 100000); stats 100000 0.91 secs, 400004 reductions, 700005 cells Cheers, Albert -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |