Τα πάντα για τον λογικό και συναρτησιακό προγραμματισμό

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Τα πάντα για τον λογικό και συναρτησιακό προγραμματισμό

Δημοσίευσηαπό konnn » 23 Ιαν 2012, 01:38

Prolog στο Ubuntu.

Εγκαθιστούμε την swi-prolog από το τερματικό με την εντολή

Κώδικας: Επιλογή όλων
sudo apt-get install swi-prolog


Μπαίνουμε με το τερματικό στο φάκελο όπου υπάρχει η εργασία μας , πχ "test.pl" η οποία περιέχει τα εξής
Κώδικας: Επιλογή όλων
male(kostas).
male(jim).
male(john).
male(nick).
female(mary).
female(niccky).
female(joy).               
married(john,mary).
married(kostas,niccky).
                           
wife(X) :- married(Y,X), female(X).
.

Για να εκκινήσουμε την prolog γράφουμε στο τερματικό
Κώδικας: Επιλογή όλων
prolog
. Τότε βλέπουμε
Κώδικας: Επιλογή όλων
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?-


Η εντολή
Κώδικας: Επιλογή όλων
consult('test.pl').
φορτώνει-μεταγλωττίζει το αρχείο μας.

Προσοχή στις τελείες μετά τις εντολές prolog.


Για να δούμε πχ τις συζύγους γράφουμε
Κώδικας: Επιλογή όλων
wife(X)

Με το Ελληνικό ερωτηματικό (;) το σύστημα βρίσκει και μια άλλη λύση (αν υπάρχει) ,δηλαδή είναι
Κώδικας: Επιλογή όλων
?- wife(X).
X = mary ;
X = niccky.


Αν γράψουμε
Κώδικας: Επιλογή όλων
wife(joy)
Βλέπουμε αν αυτή είναι παντρεμένη, δηλ.
Κώδικας: Επιλογή όλων
?- wife(joy).
false.

?-
. Με το πλήκτρο enter τερματίζει την διαδικασία αναζήτησης.

Για να βγούμε από το σύστημα της PROLOG δίνουμε

Κώδικας: Επιλογή όλων
halt.
1 Linux: Μέτριος ┃ Προγραμματισμός: Μέτριος ┃ Αγγλικά: Προχωρημένος
2 Desktop : Ubuntu 16.04 64bit
a Intel Core i3 CPU 530 2.93GHz ‖ RAM 3824 MiB ‖ Intel DH55HC -
b nVidia Device [10de:1040] (rev a1)
c eth0: Intel 82578DC Gigabit Network Connection
3 Notebook : Ubuntu 16.04 64 bit
a Intel Core i3-2365M CPU @ 1.40GHz ‖ RAM 3854 MiB ‖ LENOVO 20197
b Intel 2nd Generation Core Processor Family Integrated Graphics Controller
c 5 wlan0: Intel Centrino Wireless-N 2230 ⋮ eth0: Realtek RTL8101E/RTL8102E

Αυτόματη υπογραφή.
Άβαταρ μέλους
konnn
Συντονιστής
Συντονιστής
 
Δημοσιεύσεις: 3564
Εγγραφή: 12 Ιούλ 2010, 17:54
Τοποθεσία: Καλαμάτα
Launchpad: konnn
Εκτύπωση

Τα πάντα για τον λογικό και συναρτησιακό προγραμματισμό

Δημοσίευσηαπό tr3quart1sta » 20 Ιαν 2014, 21:03

Ανοίγω αυτό το thread, για να γνωρίσουμε και να συζητήσουμε τα περί του συναρτησιακού προγραμματισμού.

Οι περισσότεροι από εσάς που έχετε ασχοληθεί με τον προγραμματισμό, συνήθως δίνετε μία ακολουθία από εντολές οι οποίες θα πρέπει να εκτελεστούνε με μία συγκεκριμένη σειρά. Χρησιμοποιείτε μεταβλητές οι οποίες αποθηκεύουν προσωρινά μια τιμή που πιθανότατα θα αλλάξει κάποια στιγμή. Δημιουργείτε βρόγχους, ώστε να επαναλάβετε ορισμένες εντολές πολλές φορές. Ίσως κατασκευάζετε αντικείμενα, για να δώσετε νέο νόημα στα δεδομένα σας, ακολουθώντας το προγραμματιστικό παράδειγμα του αντικειμενοστρεφούς προγραμματισμού.

Υπάρχουν, όμως, κι άλλες μεθόδοι με τις οποίες μπορεί κανείς να προσεγγίσει ένα υπολογιστικό πρόβλημα. Στον συναρτησιακό προγραμματισμό, λοιπόν, αντί για αντικείμενα στο επίκεντρο βρίσκονται οι μαθηματικές συναρτήσεις. Αυτές οι συναρτήσεις εστιάζουν κυρίως στο "τι" θέλουμε να πετύχουμε και όχι στο "πως" θέλουμε να το πετύχουμε.

Μία μεγάλη διαφορά που μπορούμε να βρούμε στον συναρτησιακό προγραμματισμό, είναι η απουσία μεταβλητών! Δεν υπάρχει, δηλαδή, μία "κατάσταση" στην οποία βρίσκεται το πρόγραμμα που μπορεί να αλλάξει αργότερα. Υπάρχουν μόνο οι συναρτήσεις, που με την είσοδο των ίδιων παραμέτρων θα πρέπει πάντα να επιστρέφουνε το ίδιο αποτέλεσμα, όσες φορές και να εκτελεστούνε και δεν τροποποιούν τίποτα (οι λεγόμενες "pure" συναρτήσεις). Μπορούμε να δηλώσουμε και σταθερές, όπου στην ουσία έχουμε μια συνάρτηση που δεν δέχεται παραμέτρους και επιστρέφει πάντα την ίδια συγκεκριμένη τιμή.

Με την απουσία μεταβλητών παρουσιάζεται ένα μικρό "πρόβλημα" στις δομές επανάληψης, καθώς συνήθως απαιτείται κάποιος μετρητής που θα ορίσει το τέλος της επανάληψης μετά από έναν συγκεκριμένο αριθμό επαναλήψεων. Την λύση έρχεται να μας την προσφέρει η μέθοδος της αναδρομής, όπου τις περισσότερες φορές η συνάρτηση καλεί τον εαυτό της, έως ότου εκπληρωθεί η συνθήκη διακοπής της μεθόδου.

Είναι σύνηθες φαινόμενο στον συναρτησιακό προγραμματισμό, οι συναρτήσεις να δέχονται ως παραμέτρους όχι μόνο συγκεκριμένες τιμές, αλλά και συναρτήσεις! Τέτοιου είδους συναρτήσεις ονομάζονται high order functions. Σε άλλες περιπτώσεις, μπορεί μια συνάρτηση να επιστρέψει μια άλλη συνάρτηση, όπου βλέπουμε το φαινόμενο του partial application.

Τι προτερήματα μπορούμε να λάβουμε από αυτό το είδος προγραμματισμού?

α) Αφού δεν μπορούμε να αλλάξουμε κάποια κατάσταση, σημαίνει ότι το προγραμμά μας δεν έχει "παρενέργειες" (side-effects). Αυτό μας εγγυά λιγότερα σφάλματα στον κώδικα.

β) Ως αποτέλεσμα, η αποσφαλμάτωση του προγράμματος γίνεται πιο εύκολη. Επίσης μπορεί να γίνει και απόδειξη ορθότητας, καθώς μιλάμε για μαθηματικές συναρτήσεις.

γ) Η διαδικασία της παράλληλης εκτέλεσης γίνεται πολύ πιο εύκολη, επειδή τα προβλήματα βρίσκονται πολλές φορές στον συγχρονισμό της πρόσβασης σε μεταβλητές των οποίων η τιμή μπορεί να αλλάξει. Και δεν έχει σημασία η σειρά με την οποία θα εκτελεστούνε οι συναρτήσεις.

δ) Μπορούμε να έχουμε πιο σύντομο και "καθαρό" κώδικα (που επίσης βοηθάει σε πιο ορθό κώδικα). Δείτε ένα παράδειγμα quicksort γραμμένο σε Java και Haskell (pure γλώσσα συναρτησιακού προγραμματισμού) αντίστοιχα:

Sorting a list of numbers: [3,1,4,1,5,9] -> [1,1,3,4,5,9]

Java:

Μορφοποιημένος Κώδικας: Επιλογή όλων
private int[] numbers;

void sort(int[] values) {

if (values == null || values.length == 0) return;

numbers = values;

quicksort(0, values.length -1);

}



void quicksort(int low, int high) {

int i = low, j = high;

int pivot = nubers[low];

while (i <= j) {

while (numbers[i] < pivot) i++;

while (numbers[j] > pivot) j--;

if (i <= j) { exchange(i,j); i++; j--; }

}

if (low < j) quicksort(low, j);

if (i < high) quicksort(i, high);

}



void exchange(int i, int j) {

int temp = numbers[i];

numbers[i] = numbers[j];

numbers[j] = temp;

}

Haskell:

Μορφοποιημένος Κώδικας: Επιλογή όλων
sort[] = []

sort(x:xs) = sort ys ++ [x] ++ sort zs

where ys = [y | y <- xs, y <= x]

zs = [z | z <- xs, x < z]


ε) Γίνεται πιο εύκολη η διάσπαση του προγράμματος σε modules, όπου έχουμε ομάδες συναρτήσεων που ανήκουνε στην ίδια κατηγορία.

Ακόμα και αν κάποιος δεν ασχοληθεί με μία καθαρά συναρτησιακή γλώσσα προγραμματισμού, βλέπουμε άλλες γνωστές γλώσσες να υιοθετούν στοιχεία και χαρακτηριστικά από αυτό το είδος. Για παράδειγμα βλέπουμε η Java στην έκδοση 8 να εισάγει τα λεγόμενα lambda expressions. Στην ουσία πρόκειται για ανώνυμες συναρτήσεις που πολλές φορές γράφονται απευθείας μέσα στην παράμετρο κάποιας άλλης συνάρτησης. Ακόμα και η κυρίαρχη γλώσσα στο Web, η Javascript προσφέρει παρόμοια λειτουργικότητα. Ένα παράδειγμα σε κώδικα:

Μορφοποιημένος Κώδικας: Επιλογή όλων
function say(word) {

console.log(word);

}



function execute(someFunction, value) {

someFunction(value);

}



execute(say, "Hello");


Μπορούμε να το γράψουμε και με άλλο τρόπο:

Μορφοποιημένος Κώδικας: Επιλογή όλων
function execute(someFunction, value) {

someFunction(value);

}



execute(function(word){ console.log(word) }, "Hello");


Με αυτόν τον τρόπο, προσφέρουμε μια επιπλέον ευελιξία στον κώδικα, καθώς η λειτουργικότητα μιας συνάρτησης μπορεί να αλλάξει δυναμικά ανάλογα με ποιά ή ποιές άλλες συναρτήσεις δέχεται ως είσοδο!

Πιστεύω ότι ο συναρτησιακός προγραμματισμός είναι μία από τις πιό ενδιαφέρουσες κατηγορίες προγραμματισμού και είναι must για κάθε developer να γνωρίζει παραδείγματα από διάφορες μορφές προγραμματισμού.

Για όποιον ενδιαφέρεται για παραπάνω πληροφορίες, μπορεί να τις βρεί σε μερικά από τα παρακάτω links:

Functional Programming is black magic.

Ένα πολύ καλό tutorial

Ένα βιβλίο

Ένα σύντομο διαδραστικό online tutorial

Εν συντωμία

Μάθημα στα ελληνικά!

Για τυχόν λάθη ή σημαντικά σημεία που ίσως να ξέχασα, πείτε μου να τα σημπληρώσω. Φυσικά περιμένω και τις δικές σας απόψεις πάνω στο functional programming!
Τελευταία επεξεργασία από konnn και 24 Ιαν 2014, 01:53, έχει επεξεργασθεί 3 φορά/ες συνολικά
Αιτία: Τροποποίηση του τίτλου για δημιουργία γενικότερου θέματος σχετικά με τον συναρτησιακό προγραμματισμό όμοια με τις υπόλοιπες γλώσσες προγραμματισμού.
Επίπεδο Γνώσεων => Linux: Μέτριο / Προγραμματισμός: Μέτριο / Αγγλικά: Πολύ καλό

Σύστημα => Lenovo X240 i5-4300U / 8GB Ram / 256GB SSD / WiFi 802.11ac Intel Dual-Band 7260
tr3quart1sta
babeTUX
babeTUX
 
Δημοσιεύσεις: 9
Εγγραφή: 07 Μαρ 2010, 18:33
Εκτύπωση

Re: Τα πάντα για τον συναρτησιακό (functional) προγραμματισμ

Δημοσίευσηαπό konnn » 23 Ιαν 2014, 23:17

Συγχωνεύθηκαν δυο θέματα που αφορούν τον λογικό και συναρτησιακό προγραμματισμό.Το θέμα έγινε "ανακοίνωση" και μπορούμε να αναφερόμαστε εδώ για σχετικά ζητήματα-μίνι οδηγούς.

1 Linux: Μέτριος ┃ Προγραμματισμός: Μέτριος ┃ Αγγλικά: Προχωρημένος
2 Desktop : Ubuntu 16.04 64bit
a Intel Core i3 CPU 530 2.93GHz ‖ RAM 3824 MiB ‖ Intel DH55HC -
b nVidia Device [10de:1040] (rev a1)
c eth0: Intel 82578DC Gigabit Network Connection
3 Notebook : Ubuntu 16.04 64 bit
a Intel Core i3-2365M CPU @ 1.40GHz ‖ RAM 3854 MiB ‖ LENOVO 20197
b Intel 2nd Generation Core Processor Family Integrated Graphics Controller
c 5 wlan0: Intel Centrino Wireless-N 2230 ⋮ eth0: Realtek RTL8101E/RTL8102E

Αυτόματη υπογραφή.
Άβαταρ μέλους
konnn
Συντονιστής
Συντονιστής
 
Δημοσιεύσεις: 3564
Εγγραφή: 12 Ιούλ 2010, 17:54
Τοποθεσία: Καλαμάτα
Launchpad: konnn
Εκτύπωση

Re: Τα πάντα για τον συναρτησιακό (functional) προγραμματισμ

Δημοσίευσηαπό Ilias95 » 24 Ιαν 2014, 00:53

Γιατί να συγχωνευθούν θέματα με λογικό και συναρτησιακό προγραμματισμό;
Δεν πρόκειται για δύο τελείως διαφορετικά programming paradigms;
Ας πούμε ο τίτλος του νήματος με το 1ο post δεν νομίζω ότι κολλάει.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για τον συναρτησιακό (functional) προγραμματισμ

Δημοσίευσηαπό konnn » 24 Ιαν 2014, 01:48

Ilias95 έγραψε:Γιατί να συγχωνευθούν θέματα με λογικό και συναρτησιακό προγραμματισμό;
Δεν πρόκειται για δύο τελείως διαφορετικά programming paradigms;
Ας πούμε ο τίτλος του νήματος με το 1ο post δεν νομίζω ότι κολλάει.


Η αλήθεια δεν είναι πως πρόκειται για δυο διαφορετικά πράγματα αλλά για δυο αντιδιαμετρικά πράγματα και δεν είναι τυχαίο αφού σε πολλά πανεπιστήμια το μάθημα διδάσκεται με τον τίτλο "λογικός και συναρτησιακός προγραμματισμός". Διδάσκεται ώστε οι μαθητές να δουν τον διαφορετικό τρόπο σκέψης στην επίλυση ενός προβλήματος.Αυτό σε συνδυασμό με την μικρή τους χρήση τα έκανε να συνυπάρχουν.

π.χ
http://lpis.csd.auth.gr/curriculum/prolog/LFPr303.html
http://qa.auth.gr/class/1/40042580
http://www.semfe.gr/files/notes/4/introcs-slides5.pdf
http://www.cs.sfu.ca/research/groups/Lo ... ional.html

Τόσο η prolog (λογικός προγραμματισμός), η οποία είναι μια πεθαμένη πια γλώσσα όσο και η lisp και κατ' επέκταση η scheme (συναρτησιακός προγραμματισμός) είναι γλώσσες που χρησιμοποιήθηκαν στην ΤΕΧΝΗΤΗ ΝΟΗΜΟΣΥΝΗ.

Άρα, με αφορμή αυτό είπα να δημιουργήσουμε και εμείς ένα νήμα που να αφορά αυτές τις δυο σκέψεις.Το λάθος μου είναι πως στον αρχικό τίτλο δε πρόσθεσα τη λέξη "λογικός". Θα το προσθέσω.Αν υπάρχουν αντιρρήσεις-παρατηρήσεις το συζητάμε και επανερχόμαστε.
1 Linux: Μέτριος ┃ Προγραμματισμός: Μέτριος ┃ Αγγλικά: Προχωρημένος
2 Desktop : Ubuntu 16.04 64bit
a Intel Core i3 CPU 530 2.93GHz ‖ RAM 3824 MiB ‖ Intel DH55HC -
b nVidia Device [10de:1040] (rev a1)
c eth0: Intel 82578DC Gigabit Network Connection
3 Notebook : Ubuntu 16.04 64 bit
a Intel Core i3-2365M CPU @ 1.40GHz ‖ RAM 3854 MiB ‖ LENOVO 20197
b Intel 2nd Generation Core Processor Family Integrated Graphics Controller
c 5 wlan0: Intel Centrino Wireless-N 2230 ⋮ eth0: Realtek RTL8101E/RTL8102E

Αυτόματη υπογραφή.
Άβαταρ μέλους
konnn
Συντονιστής
Συντονιστής
 
Δημοσιεύσεις: 3564
Εγγραφή: 12 Ιούλ 2010, 17:54
Τοποθεσία: Καλαμάτα
Launchpad: konnn
Εκτύπωση


Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι