1
+ <!DOCTYPE html> < html lang ="bg " class ="theme-light "> < head > < meta charset ="utf-8 "> < meta name ="viewport " content ="width=device-width, initial-scale=1 "> < title > External gleam fallbacks - Обиколка на езика Gleam</ title > < meta name ="description " content ="Интерактивно въведение и справочник за езика за програмиране Gleam. Научете Gleam във вашия браузър! "> < meta property ="og:type " content ="website "> < meta property ="og:title " content ="External gleam fallbacks - Обиколка на езика Gleam "> < meta property ="og:description " content ="Интерактивно въведение и справочник за езика за програмиране Gleam. Научете Gleam във вашия браузър! "> < meta property ="og:url " content ="https://tour.gleam.run//advanced-features/external-gleam-fallbacks "> < meta property ="og:image " content ="https://gleam.run/images/og-image.png "> < meta property ="twitter:card " content ="summary_large_image "> < meta property ="twitter:url " content ="https://tour.gleam.run//advanced-features/external-gleam-fallbacks "> < meta property ="twitter:title " content ="External gleam fallbacks - Обиколка на езика Gleam "> < meta property ="twitter:description " content ="Интерактивно въведение и справочник за езика за програмиране Gleam. Научете Gleam във вашия браузър! "> < meta property ="twitter:image " content ="https://gleam.run/images/og-image.png "> < link rel ="shortcut icon " href ="https://gleam.run/images/lucy/lucy.svg "> < link rel ="stylesheet " href ="/css/fonts.css "> < link rel ="stylesheet " href ="/css/theme.css "> < link rel ="stylesheet " href ="/common.css "> < link rel ="stylesheet " href ="/css/layout.css "> < link rel ="stylesheet " href ="/css/code/syntax-highlight.css "> < link rel ="stylesheet " href ="/css/code/color-schemes/atom-one.css "> < link rel ="stylesheet " href ="/css/root.css "> < link rel ="stylesheet " href ="/css/pages/lesson.css "> < script src ="//gc.zgo.at/count.js " type ="text/javascript " data-goatcounter ="https://sgi.goatcounter.com/count "> </ script > </ head > < body id ="page-advanced-features-external-gleam-fallbacks "> < nav class ="navbar "> < a href ="/ " class ="logo "> < img src ="https://gleam.run/images/lucy/lucy.svg " alt ="Lucy the star, Gleam's mascot "> Обиколка на езика Gleam</ a > < div class ="nav-right "> < a href ="http://gleam.run " class ="link "> gleam.run</ a > < div class ="theme-picker "> < button type ="button " alt ="Switch to light mode " title ="Switch to light mode " class ="theme-button -light " data-light-theme-toggle =""> < svg id ="icon-moon " viewBox ="0 0 24 24 "> < path d ="M21.996 12.882c0.022-0.233-0.038-0.476-0.188-0.681-0.325-0.446-0.951-0.544-1.397-0.219-0.95 0.693-2.060 1.086-3.188 1.162-1.368 0.092-2.765-0.283-3.95-1.158-1.333-0.985-2.139-2.415-2.367-3.935s0.124-3.124 1.109-4.456c0.142-0.191 0.216-0.435 0.191-0.691-0.053-0.55-0.542-0.952-1.092-0.898-2.258 0.22-4.314 1.18-5.895 2.651-1.736 1.615-2.902 3.847-3.137 6.386-0.254 2.749 0.631 5.343 2.266 7.311s4.022 3.313 6.772 3.567 5.343-0.631 7.311-2.266 3.313-4.022 3.567-6.772zM19.567 14.674c-0.49 1.363-1.335 2.543-2.416 3.441-1.576 1.309-3.648 2.016-5.848 1.813s-4.108-1.278-5.417-2.854-2.016-3.648-1.813-5.848c0.187-2.032 1.117-3.814 2.507-5.106 0.782-0.728 1.71-1.3 2.731-1.672-0.456 1.264-0.577 2.606-0.384 3.899 0.303 2.023 1.38 3.934 3.156 5.247 1.578 1.167 3.448 1.668 5.272 1.545 0.752-0.050 1.496-0.207 2.21-0.465z "> </ path > </ svg > < svg id ="icon-toggle-left " viewBox ="0 0 24 24 "> < path d ="M8 4c-2.209 0-4.21 0.897-5.657 2.343s-2.343 3.448-2.343 5.657 0.897 4.21 2.343 5.657 3.448 2.343 5.657 2.343h8c2.209 0 4.21-0.897 5.657-2.343s2.343-3.448 2.343-5.657-0.897-4.21-2.343-5.657-3.448-2.343-5.657-2.343zM8 6h8c1.657 0 3.156 0.67 4.243 1.757s1.757 2.586 1.757 4.243-0.67 3.156-1.757 4.243-2.586 1.757-4.243 1.757h-8c-1.657 0-3.156-0.67-4.243-1.757s-1.757-2.586-1.757-4.243 0.67-3.156 1.757-4.243 2.586-1.757 4.243-1.757zM12 12c0-1.104-0.449-2.106-1.172-2.828s-1.724-1.172-2.828-1.172-2.106 0.449-2.828 1.172-1.172 1.724-1.172 2.828 0.449 2.106 1.172 2.828 1.724 1.172 2.828 1.172 2.106-0.449 2.828-1.172 1.172-1.724 1.172-2.828zM10 12c0 0.553-0.223 1.051-0.586 1.414s-0.861 0.586-1.414 0.586-1.051-0.223-1.414-0.586-0.586-0.861-0.586-1.414 0.223-1.051 0.586-1.414 0.861-0.586 1.414-0.586 1.051 0.223 1.414 0.586 0.586 0.861 0.586 1.414z "> </ path > </ svg > </ button > < button type ="button " alt ="Switch to dark mode " title ="Switch to dark mode " class ="theme-button -dark " data-dark-theme-toggle =""> < svg id ="icon-sun " viewBox ="0 0 24 24 "> < path d ="M18 12c0-1.657-0.673-3.158-1.757-4.243s-2.586-1.757-4.243-1.757-3.158 0.673-4.243 1.757-1.757 2.586-1.757 4.243 0.673 3.158 1.757 4.243 2.586 1.757 4.243 1.757 3.158-0.673 4.243-1.757 1.757-2.586 1.757-4.243zM16 12c0 1.105-0.447 2.103-1.172 2.828s-1.723 1.172-2.828 1.172-2.103-0.447-2.828-1.172-1.172-1.723-1.172-2.828 0.447-2.103 1.172-2.828 1.723-1.172 2.828-1.172 2.103 0.447 2.828 1.172 1.172 1.723 1.172 2.828zM11 1v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM11 21v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM3.513 4.927l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM17.653 19.067l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM1 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM21 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM4.927 20.487l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0zM19.067 6.347l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z "> </ path > </ svg > < svg id ="icon-toggle-right " viewBox ="0 0 24 24 "> < path d ="M8 4c-2.209 0-4.21 0.897-5.657 2.343s-2.343 3.448-2.343 5.657 0.897 4.21 2.343 5.657 3.448 2.343 5.657 2.343h8c2.209 0 4.21-0.897 5.657-2.343s2.343-3.448 2.343-5.657-0.897-4.21-2.343-5.657-3.448-2.343-5.657-2.343zM8 6h8c1.657 0 3.156 0.67 4.243 1.757s1.757 2.586 1.757 4.243-0.67 3.156-1.757 4.243-2.586 1.757-4.243 1.757h-8c-1.657 0-3.156-0.67-4.243-1.757s-1.757-2.586-1.757-4.243 0.67-3.156 1.757-4.243 2.586-1.757 4.243-1.757zM20 12c0-1.104-0.449-2.106-1.172-2.828s-1.724-1.172-2.828-1.172-2.106 0.449-2.828 1.172-1.172 1.724-1.172 2.828 0.449 2.106 1.172 2.828 1.724 1.172 2.828 1.172 2.106-0.449 2.828-1.172 1.172-1.724 1.172-2.828zM18 12c0 0.553-0.223 1.051-0.586 1.414s-0.861 0.586-1.414 0.586-1.051-0.223-1.414-0.586-0.586-0.861-0.586-1.414 0.223-1.051 0.586-1.414 0.861-0.586 1.414-0.586 1.051 0.223 1.414 0.586 0.586 0.861 0.586 1.414z "> </ path > </ svg > </ button > </ div > </ div > </ nav > < article id ="playground "> < section id ="left " class ="content-nav "> < div > < h2 > External gleam fallbacks</ h2 > < p > Една функция може да има и Gleam имплементация и external (външна)
2
+ имплементация. Ако има external имплементация за целта (target), за която се
3
+ компилира в момента, тя ще бъде използвана. Иначе ще се ползва Gleam
4
+ имплементацията. </ p >
5
+ < p > Това е полезно, ако една функция може да се имплементира в Gleam, но за една
6
+ от целите (targets) имаме оптимизирана имплементация. Например, виртуалната
7
+ машина на Erlang (Erlang VM) има вградена функция, която обръща списък
8
+ (reverse). Тази функция е имплементирана в нативен код. Кодът тук я използва,
9
+ когато се изпълнява в Erlang, тъй като тогава е налична. </ p >
10
+ </ div > < nav class ="prev-next "> < a href ="/advanced-features/multi-target-externals "> Назад</ a > — < a href ="/table-of-contents "> Съдържание</ a > — < a href ="/what-next "> Напред</ a > </ nav > </ section > < section id ="right "> < section id ="editor "> < div id ="editor-target "> </ div > </ section > < aside id ="output "> </ aside > </ section > </ article > < script type ="module ">
11
+ const mediaPrefersDarkTheme = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
12
+ const themeStorageKey = 'theme' ;
13
+
14
+ function getPreferredTheme ( ) {
15
+ return mediaPrefersDarkTheme . matches ? 'dark' : 'light' ;
16
+ }
17
+
18
+ function getAppliedTheme ( ) {
19
+ return document . documentElement . classList . contains ( 'theme-dark' )
20
+ ? 'dark'
21
+ : 'light' ;
22
+ }
23
+
24
+ function getStoredTheme ( ) {
25
+ return localStorage . getItem ( themeStorageKey ) ;
26
+ }
27
+
28
+ function storeTheme ( selectedTheme ) {
29
+ localStorage . setItem ( themeStorageKey , selectedTheme ) ;
30
+ }
31
+
32
+ function syncStoredTheme ( theme ) {
33
+ if ( theme === getPreferredTheme ( ) ) {
34
+ // Selected theme is the same as the device's preferred theme, so we can forget this setting.
35
+ localStorage . removeItem ( themeStorageKey ) ;
36
+ } else {
37
+ // Remember the selected theme to apply it on the next visit
38
+ storeTheme ( theme ) ;
39
+ }
40
+ }
41
+
42
+ function applyTheme ( theme , initial = false ) {
43
+ // abort if theme is already applied
44
+ if ( theme === getAppliedTheme ( ) ) return ;
45
+ // apply theme css class
46
+ document . documentElement . classList . toggle ( 'theme-dark' , theme === 'dark' ) ;
47
+ document . documentElement . classList . toggle ( 'theme-light' , theme !== 'dark' ) ;
48
+ }
49
+
50
+ function setTheme ( theme ) {
51
+ syncStoredTheme ( theme ) ;
52
+ applyTheme ( theme ) ;
53
+ }
54
+
55
+ function toggleTheme ( ) {
56
+ setTheme ( getAppliedTheme ( ) === 'dark' ? 'light' : 'dark' ) ;
57
+ }
58
+
59
+ function initThemeEvents ( ) {
60
+ // Watch the device's preferred theme and update theme if user did not select a theme
61
+ mediaPrefersDarkTheme . addEventListener ( 'change' , ( ) => {
62
+ // abort if the user already selected a theme
63
+ if ( ! ! getStoredTheme ( ) ) return ;
64
+ // update applied theme accordingly
65
+ applyTheme ( getPreferredTheme ( ) ) ;
66
+ } ) ;
67
+ // Add handlers for theme selection button
68
+ document
69
+ . querySelector ( '.theme-picker' )
70
+ ?. addEventListener ( 'click' , toggleTheme ) ;
71
+ }
72
+
73
+ function initTheme ( ) {
74
+ // apply stored or preferred theme
75
+ applyTheme ( getStoredTheme ( ) ?? getPreferredTheme ( ) ) ;
76
+ initThemeEvents ( ) ;
77
+ }
78
+
79
+ initTheme ( ) ;
80
+ </ script > < script type ="module ">
81
+ const keyHandlers = {
82
+ 'ArrowLeft' : ( ) => { window . location . href = '/advanced-features/multi-target-externals' } ,
83
+ 'ArrowRight' : ( ) => { window . location . href = '/what-next' } ,
84
+ }
85
+
86
+ document . addEventListener ( 'keydown' , function ( event ) {
87
+ // Don't hijack arrow keys when focus is on the code textarea.
88
+ if ( document . querySelector ( 'textarea.codeflask__textarea' ) === document . activeElement ) {
89
+ return ;
90
+ }
91
+
92
+ const handler = keyHandlers [ event . key ] ;
93
+ if ( handler !== undefined && handler !== null ) {
94
+ handler ( ) ;
95
+ }
96
+ } )
97
+ </ script > < script type ="gleam " id ="code "> import gleam / io
98
+
99
+ @external ( erlang , "lists" , "reverse" )
100
+ pub fn reverse_list ( items : List ( e ) ) - > List ( e ) {
101
+ tail_recursive_reverse ( items , [ ] )
102
+ }
103
+
104
+ fn tail_recursive_reverse ( items : List ( e ) , reversed : List ( e ) ) - > List ( e ) {
105
+ case items {
106
+ [ ] - > reversed
107
+ [ first , . . rest ] - > tail_recursive_reverse ( rest , [ first , . . reversed ] )
108
+ }
109
+ }
110
+
111
+ pub fn main ( ) {
112
+ io . debug ( reverse_list ( [ 1 , 2 , 3 , 4 , 5 ] ) )
113
+ io . debug ( reverse_list ( [ "a" , "b" , "c" , "d" , "e" ] ) )
114
+ }
115
+ </ script > < script src ="/index.js " type ="module "> </ script > </ body > </ html >
0 commit comments