Re: CAPI, LISP and "functional programming"
Guenther Schmidt <gue.schmidt@web.de> writes:
> Hi,
>
> I've been getting the hang now of some of the capi stuff. I now at
> least manage to display a calendar, forward months, years and select
> days. Not much sofar I know, but I'm glad I've gotten this far.
>
>
> But, somehow I feel that I'm going the wrong way. I'm still pretty new
> to GUI (and therefore CAPI) and also CL. First of all It takes me an
> awfully lot of code to set state changes, for the GUI allone,
> i.e. resetting values in this place and that place and for
> redisplaying, basically all by hand. I've been using a lot of SETFs
> and I feel I shouldn't.
>
>
> What I mean is my code doesn't look very "functionl" but rather very
> much well "imperative". I really don't see the light yet, and I have
> the feeling that the CAPI or rather CLOS and "functional programming"
> exclude each other.
Well CLOS deals with Objects and you can see Objects as "history of
frozen state". So how comes FP into play? First you can use all the
mapping functions to change states. And second you program logic can
be "full functional" programmes. The questions still remains, is that
really what you want? What's wrong with using state in some area and
getting along in other areas.
Just an example that you need "side-effects" can be seen in the
gtk-ghc stuff! This is an Hello World written in it:
module Main (Main.main) where
import Gtk
-- If you return False in the "delete_event" signal handler, GTK will
-- emit the "destroy" signal.
deleteEvent :: Event -> IO Bool
^^^^^^ This is a monadict Bool. Monads are
Hasekells way to deal with State
deleteEvent _ = do
putStrLn "delete event"
-- Returning True means you don't want the window to be destroyed.
-- This is useful for popping up 'are you sure you want to quit?' type dialogs.
return False
-- Another callback
destroyEvent :: IO ()
destroyEvent = do
putStrLn "destroy event"
mainQuit
main :: IO ()
main = do
initGUI
-- Create a new window
window <- windowNew
^^^^ this is a "sort of assignment"
-- When the window is given the "delete_event" signal (this is given
-- by the window manager, usually by the "close" option, or on the
-- titlebar), we ask it to call the deleteEvent function defined above.
onDelete window deleteEvent
-- Here we connect the "destroy" event to a signal handler.
-- This event occurs when we call widgetDestroy on the window,
-- or if we return FALSE in the "delete_event" callback.
onDestroy window destroyEvent
-- Sets the border width of the window.
containerSetBorderWidth window 10
-- Creates a new button with the label "Hello World".
buttonHW <- buttonNewWithLabel "Hello World"
^^^^^ again a sort of assignment
-- When the button receives the "clicked" signal, it will call the
-- function given as the second argument
onClicked buttonHW (putStr "Hello World\n")
-- This will cause the window to be destroyed by calling
-- widgetDestroy when "clicked". Again, the destroy
-- signal could come from here, or the window manager.
onClicked buttonHW $ do
putStrLn "A \"clicked\"-handler to say \"destroy\""
widgetDestroy window
containerAdd window buttonHW
-- This packs the button into the window (a gtk container).
widgetShow buttonHW
-- The final step is to display this newly created widget
widgetShow window
-- and the window
-- All GTK applications must have a Gtk.main. Control ends here
-- and waits for an event to occur (like a key press or
-- mouse event).
mainGUI
putStrLn "runLoop returned"
So this program written in a "pure" functional programming language
does deal with state!
So I don't think you missed something, you should accept that CAPI is
an OO-Framework, and therefor dealing with state is "natural"
Regards
Friedrich