Difference between revisions of "Yhc/Javascript/Programmers guide"

From HaskellWiki
Jump to: navigation, search
(prog web browser 2)
(echo demo program 1)
Line 6: Line 6:
 
A Javascript program running in a web browser faces environment different from "traditional": there is no input/output devices and operations as we are used to them, no file system, and no sequential flow of execution. Instead, there is the DOM tree of objects; some of them perform interaction with user input and provide visual output. and program execution is event-driven.
 
A Javascript program running in a web browser faces environment different from "traditional": there is no input/output devices and operations as we are used to them, no file system, and no sequential flow of execution. Instead, there is the DOM tree of objects; some of them perform interaction with user input and provide visual output. and program execution is event-driven.
   
This Programmers Guide, using a demo Echo program as a basis, will describe programming approaches and paradigms suitable for such environment.
+
This Programmers Guide, using the demo Echo program as a basis, will describe programming approaches and paradigms suitable for such environment.
   
 
===The [[Yhc/Javascript/Programmers_guide/Echo_demo_source|Echo]] Demo Program===
 
===The [[Yhc/Javascript/Programmers_guide/Echo_demo_source|Echo]] Demo Program===
  +
  +
The Echo demo program demonstrates primitive interaction with user input, dynamic modification of the DOM structure to show output, and integration with third-party Haskell code (Roman conversion module). It also demonstrates how Javascript exceptions can be handled, and how to measure time intervals when running in a web browser. The link in the section header points to a syntax-colored source of the demo program.
   
 
===The <code>main</code> function===
 
===The <code>main</code> function===

Revision as of 12:22, 21 November 2006

Up from the Ground

This part of the Programmers Guide is a collection of notes taken during the development of the first Haskell-in-Browser demo, a program that accepts users' input using a HTML input element, and repeats whatever the user typed upon pressing Enter. Additionally, Roman numeral conversion will occur if user's input is a decimal or a Roman numeral that can be converted. A timer is provided to measure code performance.

Programming for Web Browser

A Javascript program running in a web browser faces environment different from "traditional": there is no input/output devices and operations as we are used to them, no file system, and no sequential flow of execution. Instead, there is the DOM tree of objects; some of them perform interaction with user input and provide visual output. and program execution is event-driven.

This Programmers Guide, using the demo Echo program as a basis, will describe programming approaches and paradigms suitable for such environment.

The Echo Demo Program

The Echo demo program demonstrates primitive interaction with user input, dynamic modification of the DOM structure to show output, and integration with third-party Haskell code (Roman conversion module). It also demonstrates how Javascript exceptions can be handled, and how to measure time intervals when running in a web browser. The link in the section header points to a syntax-colored source of the demo program.

The main function

A Simple Monad

Calling Javascript from Haskell: unsafeJS

The unsafeJS function is not a function per se: it is rather a macro, or a compilation directive. Its purpose is to provide a Haskell-accessible wrapper with proper type signature for an arbitrary Javascript code which obeys certain coding rules.

The function has a type signature:

foreign import primitive unsafeJS :: String -> a

Which means that it takes a string. Type of the return value does not matter: the function itself is never executed. Its applications are detected by ycr2js at the time of Javascript generation.

The unsafeJS function should be called with a string literal. Neither explicitly coded (with (:)) list of characters nor concatenation of two or more strings will work. The converter will report an error in this situation.

A valid example of using unsafeJS is shown below:

global_YHC'_Primitive'_primIntSignum :: Int -> Int

global_YHC'_Primitive'_primIntSignum a = unsafeJS
  "var ea = exprEval(a); if (ea>0) return 1; else if (ea<0) return -1; else return 0;"

This is a Javascript overlay (in the sense that it overlays the default Prelude definition of the signum function) of a function that returns sign of an Int value.

The string literal unsafeJS is applied to is the Javascript code to be wrapped.

Below is the Javascript representation of this function found in the Echo page source.

strIdx["F_hy"] = "YHC.Primitive.primIntSignum";
...
var F_hy=new HSFun("F_hy", 1, function(a){
var ea = exprEval(a); if (ea>0) return 1; else if (ea<0) return -1; else return 0;});

Here are the rules that govern the usage of unsafeJS:

  • The unsafeJS function is contained in the UnsafeJS module and should be imported from there
  • Its argument must be a string literal, and nothing else
  • Its argument should be written entirely on a single line
  • Formal parameter names visible to Javascript are a, b, c, etc. that is single lowercase letters
  • Number of formal parameters should match the Haskell type signature
  • It is recommended to name the function's formal parameters in Haskell declaration in the same way they are visible to Javascript, i. e. a, b, c, etc.
  • Haskell values are passed to Javascript functions unevaluated: use exprEval to evaluate
  • Javascript code passed to unsafeJS should not contain outermost Javascript function declaration and curly braces: ycr2js will provide those
  • Javascript code is not limited in what it may contain*; common sense must be observed not to code in unsafe way when not really necessary: for instance it is possible to change fields of a Haskell data object from Javascript, but it is strongly discouraged: create a modified copy of the object and leave the original unchanged, like a Haskell program would do.
  • Javascript code must return a value

So, in the signum function above, first thing done is evaluation of the argument a. Because of the proper Haskell type signature provided, it is safe to expect a numeric value as result of the evaluation.

Next, usual comparisons with zero are performed, to determine the sign of the argument. Results are returned.


* For instance, inner function declaration may be used, as in this more complex example below (implementation of integer division via modulus):

global_YHC'_Primitive'_primIntegerQuot :: Integer -> Integer -> Integer
global_YHC'_Primitive'_primIntegerQuot a b = unsafeJS 
  "(function(x,y){return (x - (x % y))/y;})(exprEval(a),exprEval(b));"

The purpose of having an inner function declaration is to reuse evaluated arguments a and b: even though every expression is evaluated only once, extra call to exprEval may be avoided this way.

Calling Haskell from Javascript

Passing Primitive Values

Passing Strings

Passing Arrays

Passing Objects

Type Coercions

Getting/Setting Properties

Running Methods

DOM Framework

<once we have one...>