目次
サンプル・プログラム
2次関数
ここでは、2次関数 \( 2x^2 - 4x - 6 \) を定義してみることにしよう。
quadraticFunction1.html
20: <script>
21: /**
22: * 2次関数 2x^2-4x-6
23: * @param Number x xの値
24: * @return Number f(x)の値
25: */
26: function quadra(x) {
27: let y = 2 * x * x - 4 * x - 6;
28:
29: return y;
30: }
31:
32: // メイン・プログラム ======================================================
33: function quadraticFunction1() {
34: //変数宣言
35: let x = document.getElementById('x').value; //xの値
36: x = parseFloat(x); //小数化
37:
38: //2次関数の計算結果
39: let y = quadra(x);
40:
41: //結果を表示する
42: document.getElementById('y').innerHTML = y.toString();
43: }
44: </script>
function 関数名(引数1,引数2,...) {ここでは、2次関数 \( 2x^2 - 4x - 6 \) を計算する式を関数 quadra として定義している。引数xは、関数に与えるxの値である。
処理
}
関数の呼び出しは定義済み関数と同じで、
y = quadra(x);のように書く。変数xの値に応じた関数 quadra の計算結果を変数yに格納する。
これまで説明しなかったが、メイン・プログラム自身がユーザー定義関数になっている点にも注目してほしい。
ここでは、ユーザー定義関数 main_quadraticFunction1 がHTML文の <input type="button" id="exec"> にある onClickイベントで呼び出される。
関数の結果を一覧表にする
あらかじめ、xの最小値を x_min に、xの最大値を x_max に、xの刻み幅を dx に定数として定義しておく。forループ を使ってxの値を変化させながら、ユーザー定義関数 quadra を呼び出すことで一覧を作成する。
quadraticFunction2.html
33: window.onload = function() {
34: //定数宣言
35: const minX = -2.0, maxX = 4.0; //xの最小値,最大値
36: const dx = 0.5; //xの刻み幅
37:
38: //TABLEタグ(テンプレートリテラルを利用)
39: let html = `
40: <tr>
41: <th>x</th>
42: <th>f(x)</th>
43: </tr>
44: `;
45: //(テンプレートリテラルを使わない)
46: // let html += '<tr><th>x</th><th>f(x)</th></tr>';
47: //2次関数を計算
48: let y;
49: for (let x = minX; x <= maxX; x += dx) {
50: y = quadra(x);
51: html += `
52: <tr>
53: <td>${x}</td>
54: <td>${y}</td>
55: </tr>
56: `;
57: //(テンプレートリテラルを使わない)
58: // let html += '<tr><td>' + x + '</td><td>' + y + '</td></tr>';
59: }
60: //結果を表示する
61: document.getElementById('listFx').innerHTML = html;
62: }
ここで、見出し行をテキストにして変数 htmlに代入するとするなら、
let html = "<tr><th>x</th><th>f(x)</th></tr>";と書けばいいのだが、これでは、TABLEの列が幾つあるのか読みにくい。
そこで、テンプレートリテラルを用いて、HTML文を書くようにしてテキストを代入することにした。
let html = `テンプレートリテラルは、JavaScript ES6(ES2015)以降で利用できるようになったもので、バックティックで囲まれた範囲 `...` を、そのままテキストとして扱う。改行やタブなどの制御文字が入っていてもかまわない。
<tr>
<th>x</th>
<th>f(x)</th>
</tr>
`;
さらに便利なことに、下記のように書くことで、JavaScriptの変数(定数を含む)の値x, yを直接、テキストの中に埋め込むことができる。
html += `
<tr>
<td>${x}</td>
<td>${y}</td>
</tr>
`;
テンプレートリテラルは、IEでは利用できない。
可読性が低下するが、IEでは次のように書かなければならない。
html += '<tr><td>' + x + '</td><td>' + y + '</td></tr>';
そこで、メイン・プログラムは window.onload イベントハンドラを利用している。このイベントハンドラに代入する関数は、画面がロードされるときに自動実行する。
ここでは、イベントハンドラに代入する関数に名前が無い(無名関数)になっていることに留意してほしい。JavaScriptでは、他所からユーザー定義関数を呼び出すことがなければ、このように無名関数にすることができる。
2次関数のグラフ
グラフ描画のためにHTMLの canvas を利用する。
canvas は、画面の左上隅が原点 (0, 0) になる。また、グラフのマス目の大きさは指定したピクセル数に応じて可変となる。このため、xと quadra の結果に対していちいち座標変換をする必要があり、その処理の分だけプログラムが長くなる。
canvas の使い方については、「6.9 グラフィックキャンバスとヒアドキュメント」をご覧いただきたい。
quadraticFunction3.html
33: window.onload = function() {
34: //定数宣言
35: const minX = -2.0, maxX = 4.0; //xの最小値,最大値
36: const dx = 0.1; //xの刻み幅
37: const minY = -8.5, maxY = 10.5; //yの最小値,最大値
38:
39: //グラフ描画用canvas
40: let canvas = document.getElementById('graph');
41: let ctx = canvas.getContext('2d');
42: //表示倍率
43: let maxWidth = canvas.width;
44: let maxHeight = canvas.height;
45: let scaleX = Math.round(maxWidth / (Math.abs(minX) + Math.abs(maxX)));
46: let scaleY = Math.round(maxHeight / (Math.abs(minY) + Math.abs(maxY)));
47: //原点の表示位置
48: offsetX = (0 - minX) * scaleX;
49: offsetY = maxHeight - (0 - minY) * scaleY;
50: //グラフ領域
51: ctx.fillStyle = 'white';
52: ctx.fillRect(0, 0, maxWidth, maxHeight);
53: //外枠
54: ctx.lineWidth = 1; //線の太さ
55: ctx.strokeStyle = 'gray'; //線の色
56: ctx.strokeRect(0, 0, maxWidth, maxHeight); //外枠
57: //X軸・Y軸
58: ctx.strokeStyle = 'black';
59: ctx.lineCap = 'square';
60: ctx.beginPath();
61: ctx.moveTo(0, offsetY);
62: ctx.lineTo(maxWidth, offsetY); //X軸
63: ctx.moveTo(offsetX, 0);
64: ctx.lineTo(offsetX, maxHeight); //Y軸
65: ctx.stroke();
66:
67: //2次関数のグラフ
68: let x = minX; //xの初期値
69: let x0 = minX * scaleX + offsetX; //直前のx座標
70: let y0 = (0 - quadra(minX)) * scaleY + offsetY; //直前のy座標
71: ctx.lineWidth = 2;
72: ctx.strokeStyle = 'blue';
73: while (x <= maxX) {
74: let x1 = x * scaleX + offsetX; //x座標
75: let y1 = (0 - quadra(x)) * scaleY + offsetY; //y座標
76: ctx.beginPath();
77: ctx.moveTo(x0, y0);
78: ctx.lineTo(x1, y1);
79: ctx.stroke();
80: x0 = x1; //直前のx座標入れ換え
81: y0 = y1; //直前のy座標入れ換え
82: x += dx; //次のx
83: }
84: }
うるう年判定
ここでは、「3.1 if~else文」で紹介したうるう年判定プロシージャをユーザー定義関数にしてみよう。
プログラム "isleap.html" は、開始年と期間を入力し計算ボタンをクリックすると、うるう年か平年かを判定し一覧表示する。
うるう年判定を行うユーザー定義関数 isleap は、西暦年yearを引数にして、「3.1 if~else文」で紹介したプロシージャをそのまま関数化している。戻り値は、うるう年の時はtrue、平年の時はfalseだ。
isLeapYear.html
20: /**
21: * 指定した年がうるう年かどうかを求める.
22: * @param Number year 西暦年
23: * @return Boolean true:うるう年/false:平年
24: */
25: function isLeapYear(year) {
26: let ret; //戻り値
27:
28: if (year % 400 === 0) {
29: ret = true;
30: } else if (year % 100 === 0) {
31: ret = false;
32: } else if (year % 4 === 0) {
33: ret = true;
34: } else {
35: ret = false;
36: }
37:
38: return ret;
39: }
isLeapYear.html
58: for (let year = start; year < (start + period); year++) {
59: let ret = isLeapYear(year) ? 'うるう年' : '平年';
三項演算子は
(条件) ? 値1 : 値2のようにして用い、条件がtrueの時に値1を、そうでないときに値2を返す。
if文のようにブロック文として複雑な処理を行う必要がないときに重宝する演算子だ。
returnのないユーザー定義関数の戻り値
noReturn.html
21: /**
22: * returnのないユーザー関数
23: * @param なし
24: * @return なし
25: */
26: function noReturn() {
27: }
無名関数とアロー関数
半径 \( r \) から円の面積を求める公式は \( \pi \times r^2 \) だから――
calcAreaOfCircle.html
21: /**
22: * 円の面積を求める
23: * @param Number r 半径
24: * @return Number 円の面積
25: */
26: function areaOfCircle1(r) {
27: let y = Math.PI * Math.pow(r, 2); // Math.PI * r * r でも同じ
28: return y;
29: }
この関数を前述の無名関数を使って表すと――
calcAreaOfCircle.html
31: // 円の面積を求める(無名関数版)
32: const areaOfCircle2 = function (r) {
33: let y = Math.PI * Math.pow(r, 2);
34: return y;
35: }
calcAreaOfCircle.html
37: // 円の面積を求める(アロー関数版)
38: const areaOfCircle3 = (r) => Math.PI * Math.pow(r, 2);
39:
アロー関数は、次のように記述する。
const 関数名 = (引数1, 引数2, ...) => 関数式;アロー関数は、if文やfor文のような制御文を伴わない単一の式として表せるような関数を定義するときに用いられることがある。
読みやすいプログラムとは
「第8章 読みやすいプログラム」であらためて整理するが、プログラムは論文と同じ論理的な読み物である。論文と同じで、査読(レビュー)されたり、ライブラリ参照されたり‥‥最初に書いたときより、むしろ稼働後に読まれることの方が多い。
プログラミングを仕事とするときは、他人が読みやすいプログラムを書くことが求められる。プロジェクトや会社によってはコーディング規約を用意しているところもある。
万国共通のコーディング規約というものは無い。その組織が用意したガイドラインと考えてほしい。そのガイドラインを守らなくてもプログラムは動くのだが、チーム開発の効率アップのために用意される。
また、趣味で/個人でプログラミングを楽しむ方も、将来仕事をプログラミングに携わるかもしれないし、それでなくても、自分のプログラムを1週間後に見直したときに細かいロジックが分からなくなっているかもしれない。
というわけで、仕事にしても趣味にしても、読みやすいプログラムを書くことのメリットは大きい。
ここでは、よくあるコーディング規約から汎用性があり、かつJavaScript向きのものを取り出して、この連載独自のコーディング規約として紹介していく。
読みやすいプログラム:関数名
●関数の命名規則
- 関数の機能を動詞で表現する。
- 並べる順序は動詞+目的語(形容詞、名詞など)
- 発音しやすい英単語を並べる。
- 単語はローワーキャメルケースで並べる。
- 単語は最大3つ程度まで。
- 真偽値を戻す関数はis, can, hasではじめる。
これを並べると isLeapYear となる。このとき、最初の単語の頭文字は小文字で、途中の単語の頭文字を大文字にする記述法をローワーキャメルケースと呼ぶ。ちなみに、最初の単語の頭文字も大文字で IsLeapYear とするのはアッパーキャメルケースと呼ぶ
英単語で命名することに抵抗があるかもしれないが、名前として日本語を使えるプログラミング言語は少ない(皆無ではないが)。もしローマ字表記を用いるとするならば、"uruudoshikadouka" となり、さすがに読みにくい。
英語で書くことのメリットは、目的語より動詞が先にくることだ。関数の機能を動詞で表現すると、関数名からすぐに機能概要を読み取ることができる。
また、発音しやすいという規則も大切だ。チーム開発しているときに、ディスカッションは音声によることが多い。このとき、名前の発音がしにくいと効率が落ちる。日本語で会話している中で英単語の名前が挙がると、関数名や変数名であることがすぐ分かる。
英語が苦手な方は、Google翻訳やDeepL翻訳を使ってみてほしい。たとえば、DeepL翻訳に「今年はうるう年ですか?」と入力すると、"Is this a leap year ?" という翻訳結果が返ってくる。ここから、isLeapYear を命名することができる。
英単語を並べる場合、単に leapYear だけでは関数の機能が分からない。
getLeapYear は、うるう年を取得するという意味になってしまい、判定機能ではなくなる。
真偽値を返す関数の場合、肯定の返す命名をする。メインプログラムの目的によっては、うるう年でない年を判定してtrueを返す関数が必要となることがあるかもしれないが、isnotLeapYear と命名して true が返る場合を考えると混乱する。素直に isLeapYear にして、メインプログラム側で false を判定するようにした方がいい。
なお、命名規則をアッパーキャメルケースに統一し、IsLeapYear と命名することも間違いではない。ただ、いずれ紹介することになるが、クラス名にアッパーキャメルケースを使用するので、ここでは関数名はローワーキャメルケースで書くものと覚えておいてほしい。
また、単語の区切りにアンダーバー _ を使い、is_leap_year のように命名する方式をスネークケースと呼ぶ。ここでは使わないが、Python ではスネークケースが好まれる。
読みやすいプログラム:関数の参照透過性
一方で、同じ引数を渡しても、何らかの要因によって戻り値が変化するものは関数とは呼ばない。
ここで問題になるのが、関数の中で外部変数やAPI、インターフェースなどを参照し、その結果によって戻り値が異なる場合である。引数に連動して外部変数やAPI、インターフェースからの応答が異なるような仕組みであれば参照透過性は担保できるが、そうでないものは参照透過性がないということになる。参照透過性がないと、プログラムの流れを追うのが難しくなる。
isleapNow.html
43: /**
44: * 今年はうるう年かどうかを判定する.
45: * 参照透過性がない関数.
46: * @param なし
47: * @return Boolean true:うるう年/false:平年
48: */
49: function isLeapYearNow() {
50: let ret; //戻り値
51:
52: if (Year % 400 === 0) {
53: ret = true;
54: } else if (Year % 100 === 0) {
55: ret = false;
56: } else if (Year % 4 === 0) {
57: ret = true;
58: } else {
59: ret = false;
60: }
61:
62: return ret;
63: }
isleapNow.html
65: // メイン・プログラム ======================================================
66: Now = new Date();
67: let Year = Now.getFullYear();
68: let ret = isLeapYearNow() ? 'うるう年' : '平年';
69: document.write('今年は' + ret + 'である.');
70: </script>
関数 isLeapYearNow の動きを読み取るには、別の所にある変数 Year の挙動を追わなければならず、プログラムの可読性が低下してしまう。
そこで、変数 Year を、以前つくったユーザー関数 isLeapYear に渡してやれば参照透過性を担保できる。
APIやインターフェースから応答してきたデータも、いったん変数に代入しユーザー関数に渡してやることで、参照透過性を担保できる。
コラム:イベント駆動型プログラミング
同期は、ハンドラの処理が終了するまでメイン・プログラムに戻らない。
非同期は、ハンドラの処理が終了するかどうかに関わらず、メイン・プログラムは並行して実行していく。
同期の問題点は、ハンドラの処理が遅くなると、その分、メイン・プログラムの実行再開が遅れ、画面がフリーズしたようになることだ。
では、非同期にすればいいかというと、今度は、メイン・プログラムの中でハンドラの処理結果を必要としているのに、それに間に合わず、メイン・プログラムが異常な動きをし始めることがある。
また、ハンドラに参照透過性がないと、メインプログラムや他のスレッドの影響を受けて動作が変わる場合がある。あらかじめ、そのことを設定に盛り込み、漏れなくテスト仕様を用意できているならともかく、設計もテストケースも複雑になるので、できる限り避けるべきである。
ハンドラが同期か非同期かはプログラミング言語によって異なる。JavaScriptは原則として非同期であるため、メイン・プログラム側でハンドラの処理結果を待つ必要がある。
これまで例題で取り上げてきたプログラムはハンドラ(ユーザー定義関数)の処理が単純なので、意識して非同期処理は行っていないが、これから仕事としてプログラム開発する方は、常に同期か非同期を意識するようにしてほしい。
コラム:様々なプログラミング言語でうるう年判定を書いてみた
! うるう年の判定:FORTRAN SUBROUTINE IS_LEAP_YEAR(YEAR, RESULT) INTEGER YEAR, RESULT IF (MOD(YEAR, 4) .EQ. 0) THEN IF (MOD(YEAR, 100) .NE. 0 .OR. MOD(YEAR, 400) .EQ. 0) THEN RESULT = 1 ELSE RESULT = 0 ENDIF ELSE RESULT = 0 ENDIF RETURN END PROGRAM MAIN INTEGER YEAR, RESULT YEAR = 2023 CALL IS_LEAP_YEAR(YEAR, RESULT) IF (RESULT .EQ. 1) THEN WRITE(*,*) YEAR, '年はうるう年である.' ELSE WRITE(*,*) YEAR, '年はうるう年ではない.' ENDIF STOP END
*> うるう年の判定:COBOL IDENTIFICATION DIVISION. PROGRAM-ID. LeapYearProgram. DATA DIVISION. WORKING-STORAGE SECTION. 01 YEAR PIC 9(4). 01 RESULT PIC 9(4) VALUE 0. 01 DIV PIC 9(4) VALUE 0. 01 MOD PIC 9(3) VALUE 0. PROCEDURE DIVISION. MOVE 2024 TO YEAR PERFORM IS-LEAP-YEAR. IF RESULT = 1 DISPLAY YEAR "年はうるう年である." ELSE DISPLAY YEAR "年はうるう年でない." END-IF. STOP RUN. IS-LEAP-YEAR. MOVE 0 TO RESULT DIVIDE YEAR BY 4 GIVING DIV REMAINDER MOD. IF MOD = 0 ADD 1 TO RESULT DIVIDE YEAR BY 100 GIVING DIV REMAINDER MOD IF MOD = 0 MOVE 0 TO RESULT DIVIDE YEAR BY 400 GIVING DIV REMAINDER MOD IF MOD = 0 ADD 1 TO RESULT END-IF END-IF END-IF.
{ うるう年の判定:Pascal } program LeapYearProgram; uses SysUtils; function isLeapYear(year: integer): boolean; begin if year mod 400 = 0 then isLeapYear := true else if year mod 100 = 0 then isLeapYear := false else if year mod 4 = 0 then isLeapYear := true; end; var year: integer; begin year := 2024; if isLeapYear(year) then writeln(year, '年は うるう年である.') else writeln(year, '年は うるう年でない.'); end.
下記プログラムではif文のスタックを明確にするためにインデントを設けているが、if文はthenで閉じる決まりなので、Python のようにインデントが必須というわけではない。変数を宣言することはできるが、計算する前にスタックにプッシュしなければならない。
\ うるう年判定:Forth VARIABLE year \ yearという変数を宣言 : is-leap-year ( year -- flag ) dup 400 mod 0= if drop true else dup 100 mod 0= if drop false else dup 4 mod 0= if drop true else drop false then then then ; : main 2023 year ! \ 2023をyear変数に代入 year @ \ 変数yearの値をスタックにpush is-leap-year if year @ . ." 年は うるう年である。" cr else year @ . ." 年は うるう年ではない。" cr then ; main
/* うるう年判定:C */ #include <stdbool.h> #include <stdio.h> bool isLeapYear(int year) { bool result = false; if (year % 400 == 0) { result = true; } else if (year % 100 == 0) { result = false; } else if (year % 4 == 0) { result = true; } return result; } int main(void) { int year = 2023; if (isLeapYear(year)) { printf("%d年は うるう年である.", year); } else { printf("%d年は うるう年ではない.", year); } }
//うるう年判定:C++ #include <iostream> bool isLeapYear(int year) { bool result = false; if (year % 400 == 0) { result = true; } else if (year % 100 == 0) { result = false; } else if (year % 4 == 0) { result = true; } return result; } int main(void) { int year = 2023; std::cout << year << "年は うるう年" << (isLeapYear(year) ? "である." : "ではない.") << std::endl; }
//うるう年判定:Rust fn isLeapYear(year: i32) -> bool { if year % 400 == 0 { true } else if year % 100 == 0 { false } else if year % 4 == 0 { true } else { false } } fn main() { let year = 2023; if isLeapYear(year) { println!("{}年は うるう年である.", year); } else { println!("{}年は うるう年ではない.", year); } }
Module CheckLeapYear Function IsLeapYear(ByVal year As Integer) As Boolean If year Mod 400 = 0 Then Return True ElseIf year Mod 100 = 0 Then Return False ElseIf year Mod 4 = 0 Then Return True Else Return False End If End Function Sub Main() Dim year As Integer = 2023 If IsLeapYear(year) Then Console.WriteLine(year & "年は うるう年である。") Else Console.WriteLine(year & "年は うるう年ではない。") End If End Sub End Module
# うるう年判定:R isLeapYear <- function(year) { result <- FALSE if (year %% 400 == 0) { result <- TRUE } else if (year %% 100 == 0) { result <- FALSE } else if (year %% 4 == 0) { result <- TRUE } return(result) } # メイン処理 year <- 2023 if (isLeapYear(year)) { cat(year, "年はうるう年である。\n") } else { cat(year, "年はうるう年ではない。\n") }
#うるう年判定:Perl sub isLeapYear { my ($year) = @_; if ($year % 400 == 0) { $result = 1; } elsif ($year % 100 == 0) { $result = 0; } elsif ($year % 4 == 0) { $result = 1; } else { $result = 0; } return $result; } my $year = 2023; if (isLeapYear($year) == 1) { print "$year 年はうるう年である."; } else { print "$year 年はうるう年ではない."; }
#うるう年判定:Ruby def isLeapYear?(year) if (year % 400 === 0) result = true elsif (year % 100 === 0) result = false; elsif (year % 4 === 0) result = true else result = false end return result end year = 2023 result = isLeapYear?(year) ? 'である.' : 'ではない.' puts "#{year}年は うるう年#{result}"
<?php //うるう年判定:PHP function isLeapYear($year) { if ($year % 400 === 0) $result = true; else if ($year % 100 === 0) $result = false; else if ($year % 4 === 0) $result = true; else $result = false; return $result; } $year = 2023; $result = isLeapYear($year) ? 'である.' : 'ではない.'; print $year . '年は うるう年' . $result; ?>
//うるう年判定:Java import java.util.*; public class Main { //うるう年判定:Java public static boolean isLeapYear(int year) { boolean result = false; if (year % 400 == 0) result = true; else if (year % 100 == 0) result = false; else if (year % 4 == 0) result = true; return result; } public static void main(String[] args) throws Exception { int year = 2023; String result = Main.isLeapYear(year) ? "である." : "ではない."; System.out.println(year + "年は うるう年" + result); } }
//うるう年の判定:TypeScript function isLeapYear(year: number):boolean { let ret: boolean; //戻り値 if (year % 400 === 0) { ret = true; } else if (year % 100 === 0) { ret = false; } else if (year % 4 === 0) { ret = true; } else { ret = false; } return ret; } const year: number = 2100; const isLeap: boolean = isLeapYear(year); if (isLeap) { console.log(`${year}年はうるう年である.`); } else { console.log(`${year}年はうるう年ではない.`); }
//うるう年判定:Go package main import ("fmt") func isLeapYear(year int) bool { var result bool if (year % 400 == 0) { result = true } else if (year % 100 == 0) { result = false } else if (year % 4 == 0) { result = true } else { result = false } return result } func main() { var year int year = 2023 if isLeapYear(year) { fmt.Printf("%d年はうるう年です。\n", year) } else { fmt.Printf("%d年はうるう年ではありません。\n", year) } }
#うるう年判定:Python def isLeapYear(year): if year % 400 == 0: result = True elif year % 100 == 0: result = False elif year % 4 == 0: result = True else: result = False return result year = 2023 if isLeapYear(year): result = "である." else: result = "ではない." print(year, "年は うるう年", result)
//うるう年判定:Objective-C #import <Foundation/Foundation.h> BOOL isLeapYear(NSInteger year) { BOOL ret = NO; if (year % 400 == 0) { ret = YES; } else if (year % 100 == 0) { ret = NO; } else if (year % 4 == 0) { ret = YES; } else { ret = NO; } return ret; } int main(int argc, const char * argv[]) { @autoreleasepool { NSInteger year = 2024; if (isLeapYear(year)) { NSLog(@"%ld年はうるう年である.", (long)year); } else { NSLog(@"%ld年はうるう年でない.", (long)year); } } return 0; }
//うるう年判定:Swift func isLeapYear(_ year: Int) -> Bool { var ret: Bool if year % 400 == 0 { ret = true } else if year % 100 == 0 { ret = false } else if year % 4 == 0 { ret = true } else { ret = false } return ret } let year = 2023 if isLeapYear(year) { print("\(year)年はうるう年でらる.") } else { print("\(year)年はうるう年ではない.") }
;うるう年判定:Lisp (defun isLeapYear (year) (if (zerop (mod year 400)) t (if (zerop (mod year 100)) nil (if (zerop (mod year 4)) t nil))) ) (setq year 2023) (if (isLeapYear year) (format t "~A 年はうるう年である.~%" year) (format t "~A 年はうるう年ではない.~%" year))
--うるう年判定:Haskell isLeapYear :: Int -> Bool isLeapYear year | (year `mod` 4 == 0) && (year `mod` 100 /= 0) = True | year `mod` 400 == 0 = True | otherwise = False main = do let year = 2023 ::Int if isLeapYear year then putStrLn $ show year ++ "年はうるう年です。" else putStrLn $ show year ++ "年はうるう年ではありません。"
%うるう年判定:Prolog isLeapYear(Year) :- 0 is Year mod 400, !. isLeapYear(Year) :- 0 is Year mod 100, !, fail. isLeapYear(Year) :- 0 is Year mod 4, !. main(Year) :- (isLeapYear(Year) -> format('~w 年はうるう年です。', [Year]); format('~w 年はうるう年ではありません。', [Year]) ). :- main(2023).
--うるう年判定:MySQL DELIMITER // CREATE PROCEDURE isLeapYear(IN year INT, OUT message VARCHAR(50)) BEGIN DECLARE result BOOLEAN DEFAULT FALSE; IF (year % 400 = 0) THEN SET result = TRUE; ELSEIF (year % 100 = 0) THEN SET result = FALSE; ELSEIF (year % 4 = 0) THEN SET result = TRUE; END IF; IF result THEN SET message = CONCAT(year, '年はうるう年です'); ELSE SET message = CONCAT(year, '年はうるう年ではありません'); END IF; END // DELIMITER ; SET @year = 2024; SET @message = ''; CALL IsLeapYear(@year, @message); SELECT @message;
ここでは2次関数 \( 2x^2 - 4x - 6 \) や、うるう年判定処理を例題に、関数値を一覧表にしたりグラフ描画してみる。同時に、テンプレートリテラルや三項演算子について学ぶ。
自分で関数を定義できるようになると、プログラミングの範囲が飛躍的に広がる。